Changeset b7d92b96


Ignore:
Timestamp:
Jun 6, 2019, 3:40:48 PM (5 years ago)
Author:
Aaron Moss <a3moss@…>
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
Message:

More resolver porting

Location:
src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Node.hpp

    rd3b2c32a rb7d92b96  
    1818#include <cassert>
    1919#include <iosfwd>
     20#include <type_traits> // for remove_reference
    2021
    2122#include "Common/ErrorObjects.h"  // for SemanticErrorException
     
    8283};
    8384
    84 // Mutate a node, non-member function to avoid static type
    85 // problems and be able to use auto return
     85/// Mutate a node, non-member function to avoid static type
     86/// problems and be able to use auto return
    8687template<typename node_t>
    8788node_t * mutate( const node_t * node ) {
     
    9596        );
    9697        return node->clone();
     98}
     99
     100/// Mutate a node field (only clones if not equal to existing value)
     101template<typename node_t, typename field_t>
     102const 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;
    97112}
    98113
  • src/ResolvExpr/CurrentObject.cc

    rd3b2c32a rb7d92b96  
    579579} // namespace ResolvExpr
    580580
     581namespace 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
    581603// Local Variables: //
    582604// tab-width: 4 //
  • src/ResolvExpr/CurrentObject.h

    rd3b2c32a rb7d92b96  
    1717
    1818#include <list>   // for list
     19#include <memory> // for unique_ptr
    1920#include <stack>  // for stack
     21#include <vector>
    2022
    2123class Designation;
     
    5254} // namespace ResolvExpr
    5355
     56namespace 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
    5475// Local Variables: //
    5576// tab-width: 4 //
  • src/ResolvExpr/Resolver.cc

    rd3b2c32a rb7d92b96  
    165165                void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) {
    166166                        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 ) ) {
    168168                                        // cast is to the same type as its argument, so it's unnecessary -- remove it
    169169                                        expr = castExpr->arg;
     
    965965                }
    966966
     967                /// always-accept candidate filter
     968                bool anyCandidate( const Candidate & ) { return true; }
     969
    967970                /// Calls the CandidateFinder and finds the single best candidate
    968971                CandidateRef findUnfinishedKindExpression(
    969972                        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 = {}
    971974                ) {
    972975                        if ( ! untyped ) return nullptr;
     
    10561059                                ) {
    10571060                                        // 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 );
    10611063                                }
    10621064                                return castExpr;
     
    10681070                        }
    10691071                };
     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                }
    10701083
    10711084                /// Establish post-resolver invariants for expressions
     
    10821095                        StripCasts_new::strip( expr );
    10831096                }
    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
    10851130                /// resolve `untyped` to the expression whose candidate satisfies `pred` with the
    10861131                /// lowest cost, returning the resolved version
     
    10941139                        finishExpr( choice->expr, choice->env, untyped->env );
    10951140                        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;
    10961154                }
    10971155
     
    11251183
    11261184                ast::ptr< ast::Type > functionReturn = nullptr;
    1127                 // ast::CurrentObject currentObject = nullptr;
     1185                ast::CurrentObject currentObject = nullptr;
    11281186                bool inEnumDecl = false;
    11291187
     
    11411199                void previsit( const ast::PointerType * );
    11421200
    1143                 void previsit( const ast::ExprStmt * );
    1144                 void previsit( const ast::AsmExpr * );
     1201                const ast::ExprStmt * previsit( const ast::ExprStmt * );
     1202                const ast::AsmExpr * previsit( const ast::AsmExpr * );
    11451203                void previsit( const ast::AsmStmt * );
    1146                 void previsit( const ast::IfStmt * );
    1147                 void previsit( const ast::WhileStmt * );
    1148                 void previsit( const ast::ForStmt * );
    1149                 void previsit( const ast::SwitchStmt * );
    1150                 void previsit( const ast::CaseStmt * );
    1151                 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 * );
    11521210                void previsit( const ast::ReturnStmt * );
    11531211                void previsit( const ast::ThrowStmt * );
     
    11961254
    11971255        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                }
    12011269        }
    12021270
     
    12101278                const ast::StaticAssertDecl * assertDecl
    12111279        ) {
    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" );
    12141303               
    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;
    12421320        }
    12431321
     
    12481326        }
    12491327
    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;
    12841381        }
    12851382
Note: See TracChangeset for help on using the changeset viewer.