Ignore:
Timestamp:
Jun 10, 2024, 2:43:13 AM (6 weeks ago)
Author:
JiadaL <j82liang@…>
Branches:
master
Children:
42cdd07d
Parents:
d68de59
Message:
  1. Implement enum cast; 2. Change valueE so that opague enum returns quasi_void; 3. change enum hiding interpretation and pass visiting scheme
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/CandidateFinder.cpp

    rd68de59 r85855b0  
    513513                                        // add new result
    514514                                        assert( common );
    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                                         //}
     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 );
    519536                                }
    520537                        }
     
    632649                        const ast::BaseInstType * aggrInst, const ast::Expr * expr,
    633650                        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
    634655                );
    635656
     
    676697                void postvisit( const ast::QualifiedNameExpr * qualifiedExpr );
    677698
     699                const ast::Expr * makeEnumOffsetCast( const ast::EnumInstType * src,
     700                        const ast::EnumInstType * dst
     701                        , const ast::Expr * expr, Cost minCost );
     702
    678703                void postvisit( const ast::InitExpr * ) {
    679704                        assertf( false, "CandidateFinder should never see a resolved InitExpr." );
     
    876901        }
    877902
     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
    878924        /// Adds implicit struct-conversions to the alternative list
    879925        void Finder::addAnonConversions( const CandidateRef & cand ) {
     
    894940                        addAggMembers( unionInst, aggrExpr, *cand, Cost::unsafe, "" );
    895941                } else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) {
    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         }
     942                        addEnumValueAsCandidate(enumInst, aggrExpr, Cost::unsafe);
     943                }
     944        }
     945       
    914946
    915947        /// Adds aggregate member interpretations
     
    11801212        }
    11811213
     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
    11821257        void Finder::postvisit( const ast::CastExpr * castExpr ) {
    11831258                ast::ptr< ast::Type > toType = castExpr->result;
     
    12291304                                        ? conversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env )
    12301305                                        : 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                        }
    12311314
    12321315                        PRINT(
     
    12461329                                        minCastCost = thisCost;
    12471330                                        matches.clear();
    1248 
    1249 
    1250                                 }
    1251                                 // ambiguous case, still output candidates to print in error message
     1331                                }
     1332                                // ambigious case, still output candidates to print in error message
    12521333                                if ( cand->cost == minExprCost && thisCost == minCastCost ) {
    12531334                                        CandidateRef newCand = std::make_shared<Candidate>(
     
    12641345                }
    12651346                candidates = std::move(matches);
    1266 
    12671347                //CandidateList minArgCost = findMinCost( matches );
    12681348                //promoteCvtCost( minArgCost );
     
    13741454                        }
    13751455                } else {
    1376                         declList = symtab.lookupId( nameExpr->name );
     1456                        declList = symtab.lookupIdIgnoreHidden( nameExpr->name );
    13771457                }
    13781458                PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; )
     
    13861466                        ast::Expr * newExpr = data.combine( nameExpr->location, cost );
    13871467
    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 );
    13981468                        CandidateRef newCand = std::make_shared<Candidate>(
    13991469                                newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,
     
    18131883                        if ( const ast::EnumInstType * enumInstType =
    18141884                                dynamic_cast<const ast::EnumInstType *>( t ) ) {
    1815                                 if ( enumInstType->base->name == expr->type_decl->name ) {
     1885                                if ( (enumInstType->base->name == expr->type_name)
     1886                                        || (expr->type_decl && enumInstType->base->name == expr->type_decl->name) ) {
    18161887                                        Cost cost = Cost::zero;
    18171888                                        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                                         //      );
    18231889                                        CandidateRef newCand =
    18241890                                                std::make_shared<Candidate>(
     
    20962162
    20972163        return expr;
     2164}
     2165
     2166const 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;
    20982203}
    20992204
Note: See TracChangeset for help on using the changeset viewer.