Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/CandidateFinder.cpp

    r85855b0 r0f5e8cd  
    513513                                        // add new result
    514514                                        assert( common );
    515 
    516                                         auto paramAsEnum = dynamic_cast<const ast::EnumInstType *>(paramType);
    517                                         auto argAsEnum =dynamic_cast<const ast::EnumInstType *>(argType);
    518                                         if (paramAsEnum && argAsEnum) {
    519                                                 if (paramAsEnum->base->name != argAsEnum->base->name) {
    520                                                         Cost c = castCost(argType, paramType, expr, context.symtab, env);
    521                                                         if (c < Cost::infinity) {
    522                                                                 CandidateFinder subFinder( context, env );
    523                                                                 expr = subFinder.makeEnumOffsetCast(argAsEnum, paramAsEnum, expr, c);
    524                                                                 results.emplace_back(
    525                                                                         i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ),
    526                                                                         nextArg + 1, nTuples, expl.cost + c, expl.exprs.size() == 1 ? 0 : 1, j );
    527                                                                 continue;
    528                                                         } else {
    529                                                                 std::cerr << "Cannot instantiate " << paramAsEnum->base->name <<  " with " << argAsEnum->base->name << std::endl;
    530                                                         }
    531                                                 }
    532                                         }
    533                                         results.emplace_back(
    534                                                 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ),
    535                                                 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
     515                                                results.emplace_back(
     516                                                        i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ),
     517                                                        nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
     518                                        //}
    536519                                }
    537520                        }
     
    649632                        const ast::BaseInstType * aggrInst, const ast::Expr * expr,
    650633                        const Candidate & cand, const Cost & addedCost, const std::string & name
    651                 );
    652 
    653                 void addEnumValueAsCandidate(const ast::EnumInstType * instType, const ast::Expr * expr,
    654                         const Cost & addedCost
    655634                );
    656635
     
    697676                void postvisit( const ast::QualifiedNameExpr * qualifiedExpr );
    698677
    699                 const ast::Expr * makeEnumOffsetCast( const ast::EnumInstType * src,
    700                         const ast::EnumInstType * dst
    701                         , const ast::Expr * expr, Cost minCost );
    702 
    703678                void postvisit( const ast::InitExpr * ) {
    704679                        assertf( false, "CandidateFinder should never see a resolved InitExpr." );
     
    901876        }
    902877
    903         void Finder::addEnumValueAsCandidate( const ast::EnumInstType * enumInst, const ast::Expr * expr,
    904                 const Cost & addedCost
    905         ) {
    906                 if ( enumInst->base->base ) {
    907                         CandidateFinder finder( context, tenv );
    908                         auto location = expr->location;
    909                         auto callExpr = new ast::UntypedExpr(
    910                                 location, new ast::NameExpr( location, "valueE" ), {expr}
    911                         );
    912                         finder.find( callExpr );
    913                         CandidateList winners = findMinCost( finder.candidates );
    914                         if (winners.size() != 1) {
    915                                 SemanticError( callExpr, "Ambiguous expression in valueE..." );
    916                         }
    917                         CandidateRef & choice = winners.front();
    918                         choice->cost += addedCost;
    919                         addAnonConversions(choice);
    920                         candidates.emplace_back( std::move(choice) );
    921                 }
    922         }
    923 
    924878        /// Adds implicit struct-conversions to the alternative list
    925879        void Finder::addAnonConversions( const CandidateRef & cand ) {
     
    940894                        addAggMembers( unionInst, aggrExpr, *cand, Cost::unsafe, "" );
    941895                } else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) {
    942                         addEnumValueAsCandidate(enumInst, aggrExpr, Cost::unsafe);
    943                 }
    944         }
    945        
     896                        if ( enumInst->base->base ) {
     897                                CandidateFinder finder( context, tenv );
     898                                auto location = aggrExpr->location;
     899                                auto callExpr = new ast::UntypedExpr(
     900                                        location, new ast::NameExpr( location, "valueE" ), {aggrExpr}
     901                                );
     902                                finder.find( callExpr );
     903                                CandidateList winners = findMinCost( finder.candidates );
     904                                if (winners.size() != 1) {
     905                                        SemanticError( callExpr, "Ambiguous expression in valueE..." );
     906                                }
     907                                CandidateRef & choice = winners.front();
     908                                choice->cost = Cost::unsafe;
     909                                candidates.emplace_back( std::move(choice) );
     910                        }
     911
     912                }
     913        }
    946914
    947915        /// Adds aggregate member interpretations
     
    12121180        }
    12131181
    1214         // src is a subset of dst
    1215         const ast::Expr * Finder::makeEnumOffsetCast( const ast::EnumInstType * src,
    1216                 const ast::EnumInstType * dst,
    1217                 const ast::Expr * expr,
    1218                 Cost minCost ) {
    1219                
    1220                 auto srcDecl = src->base;
    1221                 auto dstDecl = dst->base;
    1222 
    1223                 if (srcDecl->name == dstDecl->name) return expr;
    1224 
    1225                 for (auto& dstChild: dstDecl->inlinedDecl) {
    1226                         Cost c = castCost(src, dstChild, false, symtab, tenv);
    1227                         ast::CastExpr * castToDst;
    1228                         if (c<minCost) {
    1229                                 unsigned offset = dstDecl->calChildOffset(dstChild.get());
    1230                                 if (offset > 0) {
    1231                                         auto untyped = ast::UntypedExpr::createCall(
    1232                                                 expr->location,
    1233                                                 "?+?",
    1234                                                 { new ast::CastExpr( expr, new ast::BasicType(ast::BasicKind::SignedInt) ),
    1235                                                 ast::ConstantExpr::from_int(expr->location, offset)});
    1236                                         CandidateFinder finder(context, tenv);
    1237                                         finder.find( untyped );
    1238                                         CandidateList winners = findMinCost( finder.candidates );
    1239                                         CandidateRef & choice = winners.front();
    1240                                         // choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
    1241                                         choice->expr = new ast::CastExpr(expr->location, choice->expr, dstChild, ast::GeneratedFlag::ExplicitCast);
    1242                                         // castToDst = new ast::CastExpr(choice->expr, dstChild);
    1243                                         castToDst = new ast::CastExpr(
    1244                                                 makeEnumOffsetCast( src, dstChild, choice->expr, minCost ),
    1245                                          dst);
    1246 
    1247                                 } else {
    1248                                         castToDst = new ast::CastExpr( expr, dst );
    1249                                 }
    1250                                 return castToDst;
    1251                         }
    1252                 }
    1253                 SemanticError(expr, src->base->name + " is not a subtype of " + dst->base->name);
    1254                 return nullptr;
    1255         }
    1256 
    12571182        void Finder::postvisit( const ast::CastExpr * castExpr ) {
    12581183                ast::ptr< ast::Type > toType = castExpr->result;
     
    13041229                                        ? conversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env )
    13051230                                        : castCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env );
    1306                        
    1307                         // Redefine enum cast
    1308                         auto argAsEnum = cand->expr->result.as<ast::EnumInstType>();
    1309                         auto toAsEnum = toType.as<ast::EnumInstType>();
    1310                         if ( argAsEnum && toAsEnum && argAsEnum->name != toAsEnum->name ) {     
    1311                                 ast::ptr<ast::Expr> offsetExpr = makeEnumOffsetCast(argAsEnum, toAsEnum, cand->expr, thisCost);
    1312                                 cand->expr = offsetExpr;
    1313                         }
    13141231
    13151232                        PRINT(
     
    13291246                                        minCastCost = thisCost;
    13301247                                        matches.clear();
    1331                                 }
    1332                                 // ambigious case, still output candidates to print in error message
     1248
     1249
     1250                                }
     1251                                // ambiguous case, still output candidates to print in error message
    13331252                                if ( cand->cost == minExprCost && thisCost == minCastCost ) {
    13341253                                        CandidateRef newCand = std::make_shared<Candidate>(
     
    13451264                }
    13461265                candidates = std::move(matches);
     1266
    13471267                //CandidateList minArgCost = findMinCost( matches );
    13481268                //promoteCvtCost( minArgCost );
     
    14541374                        }
    14551375                } else {
    1456                         declList = symtab.lookupIdIgnoreHidden( nameExpr->name );
     1376                        declList = symtab.lookupId( nameExpr->name );
    14571377                }
    14581378                PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; )
     
    14661386                        ast::Expr * newExpr = data.combine( nameExpr->location, cost );
    14671387
     1388                        // bool bentConversion = false;
     1389                        // if ( auto inst = newExpr->result.as<ast::EnumInstType>() ) {
     1390                        //      if ( inst->base && inst->base->base ) {
     1391                        //              bentConversion = true;
     1392                        //      }
     1393                        // }
     1394
     1395                        // CandidateRef newCand = std::make_shared<Candidate>(
     1396                        //      newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, bentConversion? Cost::safe: Cost::zero,
     1397                        //      cost );
    14681398                        CandidateRef newCand = std::make_shared<Candidate>(
    14691399                                newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,
     
    18831813                        if ( const ast::EnumInstType * enumInstType =
    18841814                                dynamic_cast<const ast::EnumInstType *>( t ) ) {
    1885                                 if ( (enumInstType->base->name == expr->type_name)
    1886                                         || (expr->type_decl && enumInstType->base->name == expr->type_decl->name) ) {
     1815                                if ( enumInstType->base->name == expr->type_decl->name ) {
    18871816                                        Cost cost = Cost::zero;
    18881817                                        ast::Expr * newExpr = data.combine( expr->location, cost );
     1818                                        // CandidateRef newCand =
     1819                                        //      std::make_shared<Candidate>(
     1820                                        //              newExpr, copy( tenv ), ast::OpenVarSet{},
     1821                                        //              ast::AssertionSet{}, Cost::safe, cost
     1822                                        //      );
    18891823                                        CandidateRef newCand =
    18901824                                                std::make_shared<Candidate>(
     
    21622096
    21632097        return expr;
    2164 }
    2165 
    2166 const ast::Expr * CandidateFinder::makeEnumOffsetCast( const ast::EnumInstType * src,
    2167         const ast::EnumInstType * dst,
    2168         const ast::Expr * expr,
    2169         Cost minCost ) {
    2170        
    2171         auto srcDecl = src->base;
    2172         auto dstDecl = dst->base;
    2173 
    2174         if (srcDecl->name == dstDecl->name) return expr;
    2175 
    2176         for (auto& dstChild: dstDecl->inlinedDecl) {
    2177                 Cost c = castCost(src, dstChild, false, context.symtab, env);
    2178                 ast::CastExpr * castToDst;
    2179                 if (c<minCost) {
    2180                         unsigned offset = dstDecl->calChildOffset(dstChild.get());
    2181                         if (offset > 0) {
    2182                                 auto untyped = ast::UntypedExpr::createCall(
    2183                                         expr->location,
    2184                                         "?+?",
    2185                                         { new ast::CastExpr( expr, new ast::BasicType(ast::BasicKind::SignedInt) ),
    2186                                         ast::ConstantExpr::from_int(expr->location, offset)});
    2187                                 CandidateFinder finder(context, env);
    2188                                 finder.find( untyped );
    2189                                 CandidateList winners = findMinCost( finder.candidates );
    2190                                 CandidateRef & choice = winners.front();
    2191                                 choice->expr = new ast::CastExpr(expr->location, choice->expr, dstChild, ast::GeneratedFlag::ExplicitCast);
    2192                                 castToDst = new ast::CastExpr(
    2193                                         makeEnumOffsetCast( src, dstChild, choice->expr, minCost ),
    2194                                         dst);
    2195                         } else {
    2196                                 castToDst = new ast::CastExpr( expr, dst );
    2197                         }
    2198                         return castToDst;
    2199                 }
    2200         }
    2201         SemanticError(expr, src->base->name + " is not a subtype of " + dst->base->name);
    2202         return nullptr;
    22032098}
    22042099
Note: See TracChangeset for help on using the changeset viewer.