Changes in / [73edfe9:a2a85658]


Ignore:
Location:
src
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • src/AST/porting.md

    r73edfe9 ra2a85658  
    305305* switched order of `env`, `symtab` parameters for better consistency
    306306
    307 `findMinCost`
    308 * pulled out conversion cost promotion into separate `promoteCvtCost` function
    309 
    310307[1] https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/Type-Attributes.html#Type-Attributes
    311308
  • src/ResolvExpr/CandidateFinder.cpp

    r73edfe9 ra2a85658  
    2727#include "Cost.h"
    2828#include "ExplodedArg.hpp"
    29 #include "RenameVars.h"           // for renameTyVars
    3029#include "Resolver.h"
    3130#include "ResolveTypeof.h"
     
    558557
    559558        /// Generate a cast expression from `arg` to `toType`
    560         const ast::Expr * restructureCast(
    561                 ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated
    562         ) {
    563                 if (
    564                         arg->result->size() > 1
    565                         && ! toType->isVoid()
    566                         && ! dynamic_cast< const ast::ReferenceType * >( toType )
    567                 ) {
    568                         // Argument is a tuple and the target type is neither void nor a reference. Cast each
    569                         // member of the tuple to its corresponding target type, producing the tuple of those
    570                         // cast expressions. If there are more components of the tuple than components in the
    571                         // target type, then excess components do not come out in the result expression (but
    572                         // UniqueExpr ensures that the side effects will still be produced)
    573                         if ( Tuples::maybeImpureIgnoreUnique( arg ) ) {
    574                                 // expressions which may contain side effects require a single unique instance of
    575                                 // the expression
    576                                 arg = new ast::UniqueExpr{ arg->location, arg };
    577                         }
    578                         std::vector< ast::ptr< ast::Expr > > components;
    579                         for ( unsigned i = 0; i < toType->size(); ++i ) {
    580                                 // cast each component
    581                                 ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i };
    582                                 components.emplace_back(
    583                                         restructureCast( idx, toType->getComponent( i ), isGenerated ) );
    584                         }
    585                         return new ast::TupleExpr{ arg->location, move( components ) };
    586                 } else {
    587                         // handle normally
    588                         return new ast::CastExpr{ arg->location, arg, toType, isGenerated };
    589                 }
    590         }
    591 
    592         /// Gets the name from an untyped member expression (must be NameExpr)
    593         const std::string & getMemberName( const ast::UntypedMemberExpr * memberExpr ) {
    594                 if ( memberExpr->member.as< ast::ConstantExpr >() ) {
    595                         SemanticError( memberExpr, "Indexed access to struct fields unsupported: " );
    596                 }
    597 
    598                 return memberExpr->member.strict_as< ast::NameExpr >()->name;
     559        const ast::Expr * restructureCast( const ast::Expr * arg, const ast::Type * toType, bool isGenerated ) {
     560                #warning unimplemented
     561                (void)arg; (void)toType; (void)isGenerated;
     562                assert(false);
     563                return nullptr;
    599564        }
    600565
     
    799764
    800765                        if ( auto structInst = aggrExpr->result.as< ast::StructInstType >() ) {
    801                                 addAggMembers( structInst, aggrExpr, *cand, Cost::safe, "" );
     766                                addAggMembers( structInst, aggrExpr, cand, Cost::safe, "" );
    802767                        } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) {
    803                                 addAggMembers( unionInst, aggrExpr, *cand, Cost::safe, "" );
     768                                addAggMembers( unionInst, aggrExpr, cand, Cost::safe, "" );
    804769                        }
    805770                }
     
    808773                void addAggMembers(
    809774                        const ast::ReferenceToType * aggrInst, const ast::Expr * expr,
    810                         const Candidate & cand, const Cost & addedCost, const std::string & name
     775                        const CandidateRef & cand, const Cost & addedCost, const std::string & name
    811776                ) {
    812777                        for ( const ast::Decl * decl : aggrInst->lookup( name ) ) {
    813778                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl );
    814779                                CandidateRef newCand = std::make_shared<Candidate>(
    815                                         cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost );
     780                                        *cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost );
    816781                                // add anonymous member interpretations whenever an aggregate value type is seen
    817782                                // as a member expression
    818783                                addAnonConversions( newCand );
    819784                                candidates.emplace_back( move( newCand ) );
    820                         }
    821                 }
    822 
    823                 /// Adds tuple member interpretations
    824                 void addTupleMembers(
    825                         const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand,
    826                         const Cost & addedCost, const ast::Expr * member
    827                 ) {
    828                         if ( auto constantExpr = dynamic_cast< const ast::ConstantExpr * >( member ) ) {
    829                                 // get the value of the constant expression as an int, must be between 0 and the
    830                                 // length of the tuple to have meaning
    831                                 long long val = constantExpr->intValue();
    832                                 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
    833                                         addCandidate(
    834                                                 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val },
    835                                                 addedCost );
    836                                 }
    837785                        }
    838786                }
     
    10521000                        }
    10531001
    1054                         // select first on argument cost, then conversion cost
    1055                         CandidateList minArgCost = findMinCost( matches );
    1056                         promoteCvtCost( minArgCost );
    1057                         candidates = findMinCost( minArgCost );
     1002                        // castExpr->result should be replaced with toType
     1003                        // candidates => matches
     1004
     1005                        #warning unimplemented
     1006                        (void)castExpr;
     1007                        assert(false);
    10581008                }
    10591009
     
    10711021
    10721022                void postvisit( const ast::UntypedMemberExpr * memberExpr ) {
    1073                         CandidateFinder aggFinder{ symtab, tenv };
    1074                         aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() );
    1075                         for ( CandidateRef & agg : aggFinder.candidates ) {
    1076                                 // it's okay for the aggregate expression to have reference type -- cast it to the
    1077                                 // base type to treat the aggregate as the referenced value
    1078                                 Cost addedCost = Cost::zero;
    1079                                 agg->expr = referenceToRvalueConversion( agg->expr, addedCost );
    1080 
    1081                                 // find member of the given type
    1082                                 if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) {
    1083                                         addAggMembers(
    1084                                                 structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    1085                                 } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) {
    1086                                         addAggMembers(
    1087                                                 unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    1088                                 } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) {
    1089                                         addTupleMembers( tupleType, agg->expr, *agg, addedCost, memberExpr->member );
    1090                                 }
    1091                         }
     1023                        #warning unimplemented
     1024                        (void)memberExpr;
     1025                        assert(false);
    10921026                }
    10931027
     
    10961030                }
    10971031
    1098                 void postvisit( const ast::NameExpr * nameExpr ) {
    1099                         std::vector< ast::SymbolTable::IdData > declList = symtab.lookupId( nameExpr->name );
    1100                         PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; )
    1101                         for ( auto & data : declList ) {
    1102                                 Cost cost = Cost::zero;
    1103                                 ast::Expr * newExpr = data.combine( nameExpr->location, cost );
    1104 
    1105                                 CandidateRef newCand = std::make_shared<Candidate>(
    1106                                         newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,
    1107                                         cost );
    1108                                 PRINT(
    1109                                         std::cerr << "decl is ";
    1110                                         ast::print( std::cerr, data.id );
    1111                                         std::cerr << std::endl;
    1112                                         std::cerr << "newExpr is ";
    1113                                         ast::print( std::cerr, newExpr );
    1114                                         std::cerr << std::endl;
    1115                                 )
    1116                                 newCand->expr = ast::mutate_field(
    1117                                         newCand->expr.get(), &ast::Expr::result,
    1118                                         renameTyVars( newCand->expr->result ) );
    1119                                 // add anonymous member interpretations whenever an aggregate value type is seen
    1120                                 // as a name expression
    1121                                 addAnonConversions( newCand );
    1122                                 candidates.emplace_back( move( newCand ) );
    1123                         }
     1032                void postvisit( const ast::NameExpr * variableExpr ) {
     1033                        #warning unimplemented
     1034                        (void)variableExpr;
     1035                        assert(false);
    11241036                }
    11251037
     
    11361048
    11371049                void postvisit( const ast::SizeofExpr * sizeofExpr ) {
    1138                         if ( sizeofExpr->type ) {
    1139                                 addCandidate(
    1140                                         new ast::SizeofExpr{
    1141                                                 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) },
    1142                                         tenv );
    1143                         } else {
    1144                                 // find all candidates for the argument to sizeof
    1145                                 CandidateFinder finder{ symtab, tenv };
    1146                                 finder.find( sizeofExpr->expr );
    1147                                 // find the lowest-cost candidate, otherwise ambiguous
    1148                                 CandidateList winners = findMinCost( finder.candidates );
    1149                                 if ( winners.size() != 1 ) {
    1150                                         SemanticError(
    1151                                                 sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " );
    1152                                 }
    1153                                 // return the lowest-cost candidate
    1154                                 CandidateRef & choice = winners.front();
    1155                                 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
    1156                                 choice->cost = Cost::zero;
    1157                                 addCandidate( *choice, new ast::SizeofExpr{ sizeofExpr->location, choice->expr } );
    1158                         }
     1050                        #warning unimplemented
     1051                        (void)sizeofExpr;
     1052                        assert(false);
    11591053                }
    11601054
    11611055                void postvisit( const ast::AlignofExpr * alignofExpr ) {
    1162                         if ( alignofExpr->type ) {
    1163                                 addCandidate(
    1164                                         new ast::AlignofExpr{
    1165                                                 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) },
    1166                                         tenv );
    1167                         } else {
    1168                                 // find all candidates for the argument to alignof
    1169                                 CandidateFinder finder{ symtab, tenv };
    1170                                 finder.find( alignofExpr->expr );
    1171                                 // find the lowest-cost candidate, otherwise ambiguous
    1172                                 CandidateList winners = findMinCost( finder.candidates );
    1173                                 if ( winners.size() != 1 ) {
    1174                                         SemanticError(
    1175                                                 alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " );
    1176                                 }
    1177                                 // return the lowest-cost candidate
    1178                                 CandidateRef & choice = winners.front();
    1179                                 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
    1180                                 choice->cost = Cost::zero;
    1181                                 addCandidate(
    1182                                         *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } );
    1183                         }
     1056                        #warning unimplemented
     1057                        (void)alignofExpr;
     1058                        assert(false);
    11841059                }
    11851060
    11861061                void postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ) {
    1187                         const ast::ReferenceToType * aggInst;
    1188                         if (( aggInst = offsetofExpr->type.as< ast::StructInstType >() )) ;
    1189                         else if (( aggInst = offsetofExpr->type.as< ast::UnionInstType >() )) ;
    1190                         else return;
    1191 
    1192                         for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) {
    1193                                 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member );
    1194                                 addCandidate(
    1195                                         new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv );
    1196                         }
     1062                        #warning unimplemented
     1063                        (void)offsetofExpr;
     1064                        assert(false);
    11971065                }
    11981066
     
    12711139                                                                common )
    12721140                                                ) {
    1273                                                         // generate typed expression
    1274                                                         ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{
    1275                                                                 conditionalExpr->location, r1->expr, r2->expr, r3->expr };
    1276                                                         newExpr->result = common ? common : r2->expr->result;
    1277                                                         // convert both options to result type
    1278                                                         Cost cost = r1->cost + r2->cost + r3->cost;
    1279                                                         newExpr->arg2 = computeExpressionConversionCost(
    1280                                                                 newExpr->arg2, newExpr->result, symtab, env, cost );
    1281                                                         newExpr->arg3 = computeExpressionConversionCost(
    1282                                                                 newExpr->arg3, newExpr->result, symtab, env, cost );
    1283                                                         // output candidate
    1284                                                         CandidateRef newCand = std::make_shared<Candidate>(
    1285                                                                 newExpr, move( env ), move( open ), move( need ), cost );
    1286                                                         inferParameters( newCand, candidates );
     1141                                                        #warning unimplemented
     1142                                                        assert(false);
    12871143                                                }
    12881144                                        }
     
    13421198                                                        common )
    13431199                                        ) {
    1344                                                 // generate new expression
    13451200                                                ast::RangeExpr * newExpr =
    13461201                                                        new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr };
    13471202                                                newExpr->result = common ? common : r1->expr->result;
    1348                                                 // add candidate
    1349                                                 CandidateRef newCand = std::make_shared<Candidate>(
    1350                                                         newExpr, move( env ), move( open ), move( need ),
    1351                                                         r1->cost + r2->cost );
    1352                                                 inferParameters( newCand, candidates );
     1203                                               
     1204                                                #warning unimplemented
     1205                                                assert(false);
    13531206                                        }
    13541207                                }
  • src/ResolvExpr/RenameVars.cc

    r73edfe9 ra2a85658  
    9696                }
    9797        } // namespace
    98 
    99         const ast::Type * renameTyVars( const ast::Type * t ) {
    100                 #warning unimplemented; make sure resetTyVarRenaming() updated when implemented
    101                 (void)t;
    102                 assert(false);
    103                 return t;
    104         }
    10598} // namespace ResolvExpr
    10699
  • src/ResolvExpr/RenameVars.h

    r73edfe9 ra2a85658  
    2323#include "SynTree/Visitor.h"  // for Visitor
    2424
    25 namespace ast {
    26         class Type;
    27 }
    28 
    2925namespace ResolvExpr {
    3026        /// Provides a consistent renaming of forall type names in a hierarchy by prefixing them with a unique "level" ID
    3127        void renameTyVars( Type * );
    32         const ast::Type * renameTyVars( const ast::Type * );
    3328
    3429        /// resets internal state of renamer to avoid overflow
  • src/ResolvExpr/ResolveAssertions.cc

    r73edfe9 ra2a85658  
    186186        using InferCache = std::unordered_map< UniqueId, InferredParams >;
    187187
    188         /// Lexicographically-ordered vector of costs
    189         using CostVec = std::vector< Cost >;
    190 
    191         int compare( const CostVec & a, const CostVec & b ) {
    192                 unsigned i = 0;
    193                 do {
    194                         // lex-compare where shorter one is less
    195                         if ( i == a.size() ) {
    196                                 return i == b.size() ? 0 : -1;
    197                         }
    198                         if ( i == b.size() /* && i < a.size() */ ) return 1;
    199                        
    200                         int c = a[i].compare( b[i] );
    201                         if ( c != 0 ) return c;
    202                 } while ( ++i );
    203                 assert(!"unreachable");
    204         }
    205 
    206         bool operator< ( const CostVec & a, const CostVec & b ) { return compare( a, b ) < 0; }
    207 
    208188        /// Flag for state iteration
    209189        enum IterateFlag { IterateState };
     
    216196                DeferList deferred;        ///< Deferred matches
    217197                InferCache inferred;       ///< Cache of already-inferred parameters
    218                 CostVec costs;             ///< Costs of recursive assertion satisfaction for disambiguation
    219198                SymTab::Indexer& indexer;  ///< Name lookup (depends on previous assertions)
    220199
    221200                /// Initial resolution state for an alternative
    222201                ResnState( Alternative& a, SymTab::Indexer& indexer )
    223                 : alt(a), need(), newNeed(), deferred(), inferred(), costs{ Cost::zero }, indexer(indexer) {
     202                : alt(a), need(), newNeed(), deferred(), inferred(), indexer(indexer) {
    224203                        need.swap( a.need );
    225204                }
     
    228207                ResnState( ResnState&& o, IterateFlag )
    229208                : alt(std::move(o.alt)), need(o.newNeed.begin(), o.newNeed.end()), newNeed(), deferred(),
    230                   inferred(std::move(o.inferred)), costs(o.costs), indexer(o.indexer) {
    231                         costs.emplace_back( Cost::zero );
    232                 }
     209                  inferred(std::move(o.inferred)), indexer(o.indexer) {}
    233210        };
    234211
     
    359336        };
    360337
    361         /// Map of alternative return types to recursive assertion satisfaction costs
    362         using PruneMap = std::unordered_map<std::string, CostVec>;
    363 
    364         /// Gets the pruning key for an alternative
    365         std::string pruneKey( const Alternative & alt ) {
    366                 Type* resType = alt.expr->result->clone();
    367                 alt.env.apply( resType );
    368                 std::string resKey = SymTab::Mangler::mangleType( resType );
    369                 delete resType;
    370                 return std::move( resKey );
    371         }
    372        
    373         /// Replace resnSlots with inferParams and add alternative to output list, if meets pruning
    374         /// threshold.
    375         void finalizeAssertions( ResnState& resn, PruneMap & pruneThresholds, AltList& out ) {
    376                 // prune if cheaper alternative for same key has already been generated
    377                 std::string resKey = pruneKey( resn.alt );
    378                 auto it = pruneThresholds.find( resKey );
    379                 if ( it != pruneThresholds.end() ) {
    380                         if ( it->second < resn.costs ) return;
    381                 } else {
    382                         pruneThresholds.emplace_hint( it, resKey, resn.costs );
    383                 }
    384 
    385                 // replace resolution slots with inferred params, add to output
    386                 PassVisitor<InferMatcher> matcher{ resn.inferred };
    387                 resn.alt.expr = resn.alt.expr->acceptMutator( matcher );
    388                 out.emplace_back( resn.alt );
     338        void finalizeAssertions( Alternative& alt, InferCache& inferred, AltList& out ) {
     339                PassVisitor<InferMatcher> matcher{ inferred };
     340                alt.expr = alt.expr->acceptMutator( matcher );
     341                out.emplace_back( alt );
    389342        }
    390343
     
    406359                ResnList resns{ ResnState{ alt, root_indexer } };
    407360                ResnList new_resns{};
    408                
    409                 // Pruning thresholds by result type of the output alternatives.
    410                 // Alternatives *should* be generated in sorted order, so no need to retroactively prune
    411                 PruneMap thresholds;
    412361
    413362                // resolve assertions in breadth-first-order up to a limited number of levels deep
     
    415364                        // scan over all mutually-compatible resolutions
    416365                        for ( auto& resn : resns ) {
    417                                 // stop this branch if already found a better option
    418                                 auto it = thresholds.find( pruneKey( resn.alt ) );
    419                                 if ( it != thresholds.end() && it->second < resn.costs ) goto nextResn;
    420 
    421366                                // make initial pass at matching assertions
    422367                                for ( auto& assn : resn.need ) {
     
    438383                                        // either add successful match or push back next state
    439384                                        if ( resn.newNeed.empty() ) {
    440                                                 finalizeAssertions( resn, thresholds, out );
     385                                                finalizeAssertions( resn.alt, resn.inferred, out );
    441386                                        } else {
    442387                                                new_resns.emplace_back( std::move(resn), IterateState );
     
    475420                                                goto nextResn;
    476421                                        }
    477                                         // sort by cost for overall pruning
     422                                        // sort by cost
    478423                                        CandidateCost coster{ resn.indexer };
    479424                                        std::sort( compatible.begin(), compatible.end(), coster );
    480425
     426                                        // keep map of detected options
     427                                        std::unordered_map<std::string, Cost> found;
    481428                                        for ( auto& compat : compatible ) {
     429                                                // filter by environment-adjusted result type, keep only cheapest option
     430                                                Type* resType = alt.expr->result->clone();
     431                                                compat.env.apply( resType );
     432                                                // skip if cheaper alternative already processed with same result type
     433                                                Cost resCost = coster.get( compat );
     434                                                auto it = found.emplace( SymTab::Mangler::mangleType( resType ), resCost );
     435                                                delete resType;
     436                                                if ( it.second == false && it.first->second < resCost ) continue;
     437
     438                                                // proceed with resolution step
    482439                                                ResnState new_resn = resn;
    483440
     
    495452                                                new_resn.alt.openVars = std::move(compat.openVars);
    496453
    497                                                 // mark cost of this path
    498                                                 new_resn.costs.back() += compat.cost;
    499 
    500454                                                // either add sucessful match or push back next state
    501455                                                if ( new_resn.newNeed.empty() ) {
    502                                                         finalizeAssertions( new_resn, thresholds, out );
     456                                                        finalizeAssertions( new_resn.alt, new_resn.inferred, out );
    503457                                                } else {
    504458                                                        new_resns.emplace_back( std::move(new_resn), IterateState );
Note: See TracChangeset for help on using the changeset viewer.