Changes in / [8c0d801:546e712]


Ignore:
Location:
src
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Node.hpp

    r8c0d801 r546e712  
    1818#include <cassert>
    1919#include <iosfwd>
    20 #include <type_traits> // for remove_reference
    2120
    2221#include "Common/ErrorObjects.h"  // for SemanticErrorException
     
    8382};
    8483
    85 /// Mutate a node, non-member function to avoid static type
    86 /// problems and be able to use auto return
     84// Mutate a node, non-member function to avoid static type
     85// problems and be able to use auto return
    8786template<typename node_t>
    8887node_t * mutate( const node_t * node ) {
     
    9695        );
    9796        return node->clone();
    98 }
    99 
    100 /// Mutate a node field (only clones if not equal to existing value)
    101 template<typename node_t, typename field_t>
    102 const node_t * mutate_field(
    103         const node_t * node,
    104         typename std::remove_const<typename std::remove_reference<field_t>::type>::type node_t::* field,
    105         field_t&& val
    106 ) {
    107         if ( node->*field == val ) return node;
    108        
    109         node_t * ret = mutate( node );
    110         ret->*field = std::forward< field_t >( val );
    111         return ret;
    11297}
    11398
  • src/ResolvExpr/CurrentObject.cc

    r8c0d801 r546e712  
    579579} // namespace ResolvExpr
    580580
    581 namespace ast {
    582 
    583         /// Iterates members of a type by initializer
    584         class MemberIterator {
    585         public:
    586                 virtual ~MemberIterator() {}
    587         };
    588 
    589         /// Iterates "other" types (e.g. basic, pointer) which do not change at list initializer entry
    590         class SimpleIterator final : public MemberIterator {
    591                 const Type * type = nullptr;
    592         public:
    593                 SimpleIterator( const Type * t ) : type( t ) {}
    594         };
    595 
    596         CurrentObject::CurrentObject( const ast::Type * type ) : objStack() {
    597                 objStack.emplace_back( new SimpleIterator{ type } );
    598         }
    599 
    600         #warning ast::CurrentObject port incomplete
    601 }
    602 
    603581// Local Variables: //
    604582// tab-width: 4 //
  • src/ResolvExpr/CurrentObject.h

    r8c0d801 r546e712  
    1717
    1818#include <list>   // for list
    19 #include <memory> // for unique_ptr
    2019#include <stack>  // for stack
    21 #include <vector>
    2220
    2321class Designation;
     
    5452} // namespace ResolvExpr
    5553
    56 namespace ast {
    57         // AST class types
    58         class Designation;
    59         class InitAlternative;
    60         class Type;
    61 
    62         // forward declaration of internal detail
    63         class MemberIterator;
    64 
    65         /// Builds initializer lists in resolution
    66         class CurrentObject final {
    67                 std::vector< std::shared_ptr<MemberIterator> > objStack;
    68        
    69         public:
    70                 CurrentObject() = default;
    71                 CurrentObject( const Type * type );
    72         };
    73 } // namespace ast
    74 
    7554// Local Variables: //
    7655// tab-width: 4 //
  • src/ResolvExpr/ResolveAssertions.cc

    r8c0d801 r546e712  
    342342
    343343        /// Limit to depth of recursion of assertion satisfaction
    344         static const int recursionLimit = 4;
    345         /// Maximum number of simultaneously-deferred assertions to attempt concurrent satisfaction of
    346         static const int deferLimit = 10;
     344        static const int recursionLimit = /* 10 */ 4;
    347345
    348346        void resolveAssertions( Alternative& alt, const SymTab::Indexer& indexer, AltList& out, std::list<std::string>& errors ) {
     
    371369                                                ss << tabs << "Unsatisfiable alternative:\n";
    372370                                                resn.alt.print( ss, ++tabs );
    373                                                 ss << (tabs-1) << "Could not satisfy assertion:\n";
    374                                                 assn.decl->print( ss, tabs );
     371                                                ss << --tabs << "Could not satisfy assertion:\n";
     372                                                assn.decl->print( ss, ++tabs );
    375373                                               
    376374                                                errors.emplace_back( ss.str() );
     
    386384                                                new_resns.emplace_back( std::move(resn), IterateState );
    387385                                        }
    388                                 } else if ( resn.deferred.size() > deferLimit ) {
    389                                         // too many deferred assertions to attempt mutual compatibility
    390                                         Indenter tabs{ 3 };
    391                                         std::ostringstream ss;
    392                                         ss << tabs << "Unsatisfiable alternative:\n";
    393                                         resn.alt.print( ss, ++tabs );
    394                                         ss << (tabs-1) << "Too many non-unique satisfying assignments for "
    395                                                 "assertions:\n";
    396                                         for ( const auto& d : resn.deferred ) {
    397                                                 d.decl->print( ss, tabs );
    398                                         }
    399 
    400                                         errors.emplace_back( ss.str() );
    401                                         goto nextResn;
    402386                                } else {
    403387                                        // resolve deferred assertions by mutual compatibility
     
    411395                                                ss << tabs << "Unsatisfiable alternative:\n";
    412396                                                resn.alt.print( ss, ++tabs );
    413                                                 ss << (tabs-1) << "No mutually-compatible satisfaction for assertions:\n";
     397                                                ss << --tabs << "No mutually-compatible satisfaction for assertions:\n";
     398                                                ++tabs;
    414399                                                for ( const auto& d : resn.deferred ) {
    415400                                                        d.decl->print( ss, tabs );
  • src/ResolvExpr/Resolver.cc

    r8c0d801 r546e712  
    165165                void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) {
    166166                        if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    167                                 if ( typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
     167                                if ( ResolvExpr::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 
    970967                /// Calls the CandidateFinder and finds the single best candidate
    971968                CandidateRef findUnfinishedKindExpression(
    972969                        const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind,
    973                         std::function<bool(const Candidate &)> pred = anyCandidate, ResolvMode mode = {}
     970                        std::function<bool(const Candidate &)> pred, ResolvMode mode = {}
    974971                ) {
    975972                        if ( ! untyped ) return nullptr;
     
    10591056                                ) {
    10601057                                        // 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 );
     1058                                        ast::ptr<ast::Expr> arg = castExpr->arg;
     1059                                        arg.get_and_mutate()->env = castExpr->env;
     1060                                        return arg;
    10631061                                }
    10641062                                return castExpr;
     
    10701068                        }
    10711069                };
    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                 }
    10831070
    10841071                /// Establish post-resolver invariants for expressions
     
    10951082                        StripCasts_new::strip( expr );
    10961083                }
    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 
     1084               
    11301085                /// resolve `untyped` to the expression whose candidate satisfies `pred` with the
    11311086                /// lowest cost, returning the resolved version
     
    11391094                        finishExpr( choice->expr, choice->env, untyped->env );
    11401095                        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;
    11541096                }
    11551097
     
    11831125
    11841126                ast::ptr< ast::Type > functionReturn = nullptr;
    1185                 ast::CurrentObject currentObject = nullptr;
     1127                // ast::CurrentObject currentObject = nullptr;
    11861128                bool inEnumDecl = false;
    11871129
     
    11991141                void previsit( const ast::PointerType * );
    12001142
    1201                 const ast::ExprStmt * previsit( const ast::ExprStmt * );
    1202                 const ast::AsmExpr * previsit( const ast::AsmExpr * );
     1143                void previsit( const ast::ExprStmt * );
     1144                void previsit( const ast::AsmExpr * );
    12031145                void 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 * );
     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 * );
    12101152                void previsit( const ast::ReturnStmt * );
    12111153                void previsit( const ast::ThrowStmt * );
     
    12541196
    12551197        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->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                 }
     1198                #warning unimplemented; Resolver port in progress
     1199                (void)objectDecl;
     1200                assert(false);
    12691201        }
    12701202
     
    12781210                const ast::StaticAssertDecl * assertDecl
    12791211        ) {
    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 );
     1212                ast::ptr< ast::Expr > cond = findIntegralExpression( assertDecl->cond, symtab );
     1213                if ( cond == assertDecl->cond ) return assertDecl;
     1214               
     1215                ast::StaticAssertDecl * ret = mutate( assertDecl );
     1216                ret->cond = cond;
     1217                return ret;
    12901218        }
    12911219
    12921220        void Resolver_new::previsit( const ast::ArrayType * at ) {
    1293                 handlePtrType( at, symtab );
     1221                #warning unimplemented; Resolver port in progress
     1222                (void)at;
     1223                assert(false);
    12941224        }
    12951225
    12961226        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" );
    1303                
    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;
     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);
    13201242        }
    13211243
     
    13261248        }
    13271249
    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;
     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);
    13811284        }
    13821285
Note: See TracChangeset for help on using the changeset viewer.