Goose  Diff

Differences From Artifact [b3cc176f0e]:

  • File bs/builtins/types/overloadset/invoke.cpp — part of check-in [ea17da4e19] at 2024-03-23 12:47:48 on branch trunk — structs:
    • add test for nested initialization
    • fix nested initialization
    (user: zlodo size: 5943)

To Artifact [24a6526b29]:

  • File bs/builtins/types/overloadset/invoke.cpp — part of check-in [0db147f117] at 2024-09-15 20:24:31 on branch cir-ssa-refactor — Add clang format settings, reformat everything (user: achavasse size: 5503)

1
2
3

4
5
6
7
8
9
10
11
12
13
14





15
16

17
18
19
20
21
22





23
24
25
26
27
28





29
30
31
32
33
34
35







36
37
38


39
40

41
42
43
44
45
46





47
48
49
50
51
52
53
54
55
56
57
58
59
60
61














62
63

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78














79
80
81
82
83
84
85






86
87
88
89



90
91
92
93



94
95
96
97
98
99





100
101
102
103
104
105





106
107
108
109
110
111
112
113







114
115
116
117
118
119
120
121







122
123
124
125
126
127





128
129

130
131
132


133
134
135
136
137
138
139
140
141
142
143
144
145

146
147
148
149

1
2

3
4
5
6
7
8
9
10




11
12
13
14
15
16

17
18





19
20
21
22
23
24





25
26
27
28
29
30






31
32
33
34
35
36
37
38


39
40
41

42
43





44
45
46
47
48
49














50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

65
66














67
68
69
70
71
72
73
74
75
76
77
78
79
80
81






82
83
84
85
86
87
88



89
90
91
92



93
94
95
96





97
98
99
100
101
102





103
104
105
106
107
108







109
110
111
112
113
114
115
116







117
118
119
120
121
122
123
124





125
126
127
128
129
130

131
132


133
134
135
136
137
138
139
140
141
142
143
144
145


146

147
148

149


-
+







-
-
-
-
+
+
+
+
+

-
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
+
+

-
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
+
+
+

-
-
-
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
+

-
-
+
+











-
-
+
-


-
+
#include "builtins/builtins.h"

//#define OVL_TC_DEBUG
// #define OVL_TC_DEBUG

using namespace goose::sema;

namespace goose::builtins
{
    class OverloadSetInvocationRule : public InvocationRule
    {
        public:
            Value resolveInvocation( Context& c, LocationId loc, const Value& callee, const Term& args ) const final
            {
                ProfileZoneScoped;
      public:
        Value resolveInvocation(
            Context& c, LocationId loc, const Value& callee, const Term& args ) const final
        {
            ProfileZoneScoped;

                auto pOvlSet = *FromValue< ptr< OverloadSet > >( callee );
            auto pOvlSet = *FromValue< ptr< OverloadSet > >( callee );

                #if TRACY_ENABLE
                    stringstream sstr;
                    sstr << pOvlSet->identity();
                    ProfileZoneName( sstr.str().c_str(), sstr.str().size() );
                #endif
#if TRACY_ENABLE
            stringstream sstr;
            sstr << pOvlSet->identity();
            ProfileZoneName( sstr.str().c_str(), sstr.str().size() );
#endif

                if( auto ovl = pOvlSet->getResolutionFromCache( args ) )
                    return ovl->pInvRule->resolveInvocation( c, loc, *ovl->callee, args );
                else
                    return resolve( c, loc, pOvlSet, args );
            }
            if( auto ovl = pOvlSet->getResolutionFromCache( args ) )
                return ovl->pInvRule->resolveInvocation( c, loc, *ovl->callee, args );
            else
                return resolve( c, loc, pOvlSet, args );
        }

        private:
            Value resolve( Context& c, LocationId loc, const ptr< OverloadSet >& pOvlSet, const Term& args ) const
            {
                const OverloadSet::Overload* bestOvl = nullptr;
                optional< TypeCheckingContext > bestTCC;
                optional< Term > bestSol;
      private:
        Value resolve(
            Context& c, LocationId loc, const ptr< OverloadSet >& pOvlSet, const Term& args ) const
        {
            const OverloadSet::Overload* bestOvl = nullptr;
            optional< TypeCheckingContext > bestTCC;
            optional< Term > bestSol;

                {
                    ProfileZoneScopedN( "Overload resolution" );
            {
                ProfileZoneScopedN( "Overload resolution" );

                    bool ambiguous = false;
                bool ambiguous = false;

                    if( pOvlSet->verboseResolution() )
                    {
                        DiagnosticsManager::GetInstance().emitTraceMessage( loc,
                            std::format( "invoking overload set: {}", pOvlSet->identity() ) );
                    }
                if( pOvlSet->verboseResolution() )
                {
                    DiagnosticsManager::GetInstance().emitTraceMessage(
                        loc, std::format( "invoking overload set: {}", pOvlSet->identity() ) );
                }

                    auto callPat = PrependToVectorTerm( args, HOLE( "_"_sid, "fwd"_sid ) );
                    TypeCheckingContext tcc( c );
                    for( auto&& [s,ovl,tcc] : pOvlSet->typeCheck( callPat, tcc ) )
                    {
                        if( tcc.numUnknownValues() )
                        {
                            if( pOvlSet->verboseResolution() )
                            {
                                DiagnosticsManager::GetInstance().emitTraceMessage(
                                    ovl.callee ? ovl.callee->locationId() : 0,
                                    format( "rejected candidate", tcc.score() ) );
                            }
                            continue;
                        }
                auto callPat = PrependToVectorTerm( args, HOLE( "_"_sid, "fwd"_sid ) );
                TypeCheckingContext tcc( c );
                for( auto&& [s, ovl, tcc] : pOvlSet->typeCheck( callPat, tcc ) )
                {
                    if( tcc.numUnknownValues() )
                    {
                        if( pOvlSet->verboseResolution() )
                        {
                            DiagnosticsManager::GetInstance().emitTraceMessage(
                                ovl.callee ? ovl.callee->locationId() : 0,
                                format( "rejected candidate", tcc.score() ) );
                        }
                        continue;
                    }

                        auto subs = Substitute( s, tcc );
                    auto subs = Substitute( s, tcc );

                        // Typechecking rules often end up stripping part of the original type,
                        // and we want to invoke the overload where these removals are minimized.
                        //
                        // Obvious example: if there is an overload that accepts a reference
                        // and one that accepts a value of the same type and we started with a
                        // reference, then we want to call the overload where the typechecking
                        // solution didn't strip the reference.
                        //
                        // So we add the weight of the original arguments to the cost,
                        // and remove the cost of the typechecking solution to account for that.
                        int32_t cost = tcc.cost();
                        cost += GetWeight( callPat );
                        cost -= GetWeight( subs );
                        tcc.setCost( cost );
                    // Typechecking rules often end up stripping part of the original type,
                    // and we want to invoke the overload where these removals are minimized.
                    //
                    // Obvious example: if there is an overload that accepts a reference
                    // and one that accepts a value of the same type and we started with a
                    // reference, then we want to call the overload where the typechecking
                    // solution didn't strip the reference.
                    //
                    // So we add the weight of the original arguments to the cost,
                    // and remove the cost of the typechecking solution to account for that.
                    int32_t cost = tcc.cost();
                    cost += GetWeight( callPat );
                    cost -= GetWeight( subs );
                    tcc.setCost( cost );

                        if( pOvlSet->verboseResolution() )
                        {
                            DiagnosticsManager::GetInstance().emitTraceMessage(
                                ovl.callee ? ovl.callee->locationId() : 0,
                                format( "candidate score: {}", tcc.score() ) );
                        }
                    if( pOvlSet->verboseResolution() )
                    {
                        DiagnosticsManager::GetInstance().emitTraceMessage(
                            ovl.callee ? ovl.callee->locationId() : 0,
                            format( "candidate score: {}", tcc.score() ) );
                    }

                        auto score = tcc.score();
                        if( bestTCC && score < bestTCC->score() )
                            continue;
                    auto score = tcc.score();
                    if( bestTCC && score < bestTCC->score() )
                        continue;

                        auto pps = Postprocess( subs, tcc );
                        if( !pps )
                            continue;
                    auto pps = Postprocess( subs, tcc );
                    if( !pps )
                        continue;

                        if( bestTCC && score == bestTCC->score() )
                        {
                            ambiguous = true;
                            continue;
                        }
                    if( bestTCC && score == bestTCC->score() )
                    {
                        ambiguous = true;
                        continue;
                    }

                        bestTCC = tcc;
                        bestSol = move( *pps );
                        bestOvl = &ovl;
                        ambiguous = false;
                    }
                    bestTCC = tcc;
                    bestSol = move( *pps );
                    bestOvl = &ovl;
                    ambiguous = false;
                }

                    if( ambiguous )
                    {
                        // TODO display details
                        DiagnosticsManager::GetInstance().emitErrorMessage( loc,
                            "ambiguous function call." );
                        return PoisonValue();
                    }
                if( ambiguous )
                {
                    // TODO display details
                    DiagnosticsManager::GetInstance().emitErrorMessage(
                        loc, "ambiguous function call." );
                    return PoisonValue();
                }

                    if( !bestSol )
                    {
                        // TODO display details
                        DiagnosticsManager::GetInstance().emitErrorMessage( loc,
                            "function arguments mismatch." );
                        return PoisonValue();
                    }
                if( !bestSol )
                {
                    // TODO display details
                    DiagnosticsManager::GetInstance().emitErrorMessage(
                        loc, "function arguments mismatch." );
                    return PoisonValue();
                }

                #if defined( OVL_TC_DEBUG ) && !defined( NDEBUG )
                    bestTCC->DumpParamsTraces( cout );
                    cout << endl;
                #endif
                }
#if defined( OVL_TC_DEBUG ) && !defined( NDEBUG )
                bestTCC->DumpParamsTraces( cout );
                cout << endl;
#endif
            }

                pOvlSet->addResolutionToCache( args, *bestOvl );
            pOvlSet->addResolutionToCache( args, *bestOvl );

                return bestOvl->pInvRule->invoke( c, loc, *bestOvl->callee, args, *bestSol, *bestTCC );
            }
            return bestOvl->pInvRule->invoke( c, loc, *bestOvl->callee, args, *bestSol, *bestTCC );
        }
    };

    ptr< InvocationRule >& GetOverloadSetInvocationRule()
    {
        static ptr< InvocationRule > pRule = make_shared< OverloadSetInvocationRule >();
        return pRule;
    }

    void SetupOverloadSetInvocationRule( Env& e )
    {
        e.invocationRuleSet()->addRule(
            ValueToEIR( Value(
                GetValueType< ptr< OverloadSet > >(),
            ValueToEIR( Value( GetValueType< ptr< OverloadSet > >(), ANYTERM( _ ) ) ),
                ANYTERM( _ ) ) ),
            GetOverloadSetInvocationRule() );
    }
}
} // namespace goose::builtins