Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    r99d4584 rb7d92b96  
    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
     
    10931139                        finishExpr( choice->expr, choice->env, untyped->env );
    10941140                        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;
    10951154                }
    10961155
     
    11181177        }
    11191178
    1120         class Resolver_new final 
    1121         : public ast::WithSymbolTable, public ast::WithGuards, 
    1122           public ast::WithVisitorRef<Resolver_new>, public ast::WithShortCircuiting, 
     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 = nullptr;
    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 * );
     1201                const ast::ExprStmt * previsit( const ast::ExprStmt * );
     1202                const ast::AsmExpr * previsit( const ast::AsmExpr * );
    11441203                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 * );
     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 * );
    11511210                void previsit( const ast::ReturnStmt * );
    11521211                void previsit( const ast::ThrowStmt * );
     
    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->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                }
    11971269        }
    11981270
     
    12061278                const ast::StaticAssertDecl * assertDecl
    12071279        ) {
    1208                 ast::ptr< ast::Expr > cond = findIntegralExpression( assertDecl->cond, symtab );
    1209                 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" );
    12101303               
    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);
     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;
    12381320        }
    12391321
     
    12441326        }
    12451327
    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);
     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;
    12801381        }
    12811382
Note: See TracChangeset for help on using the changeset viewer.