Goose  Diff

Differences From Artifact [e858b0d5cc]:

  • File bs/builtins/types/localvar/localvar.cpp — part of check-in [308bd3ed4d] at 2023-12-09 19:44:26 on branch trunk — Assigning something to a Decl or a TNamedDecl no longer directly declares a variable but creates an intermediate DeclWithInit or TNamedDeclWithInit, which declare variables when dropped. (user: zlodo size: 9651)

To Artifact [8636fa2d96]:

  • File bs/builtins/types/localvar/localvar.cpp — part of check-in [1f1faa7fe2] at 2023-12-11 00:08:09 on branch trunk — Move the local type inference code out of locvar and into its own function so it can be reused for struct members (user: zlodo size: 6033)

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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187


188
189
190
191
192
193
194
195
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







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

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





-
-
-
+
+
-







        if( !cfg )
            return PoisonValue();

        auto bb = cfg->currentBB();
        if( !bb )
            return PoisonValue();

        // To infer the type and obtain a suitable initialization function, we typecheck
        //          ( $$T, _ ( MutRef[$$T], initValType ) initFunc )
        // against  ( pat, Initialize                              )
        //
        // Where:
        //   pat is the type pattern provided for the declaration,
        //   initValType is the initialization expression's type,
        //   Initialize is the Initialize overload set.
        //
        // The possible types that can be infered according to the initialization expression
        // are therefore defined by the Initialize overloads.

        auto type = InferTypeFromTExprAndInitializer( c, typeTExpr, initVal );
        // The best solution (if any) will give us the wanted type and
        // the function to invoke to initialize it.

        if( type.isPoison() )
        // Create the _ texpr.
        static auto TVarAny = ValueToEIR( ToValue( TVar( "_"_sid ) ) );

        // The $$T texpr.
        static auto TTVarT = ValueToEIR( ToValue( TTVar( "T"_sid ) ) );

        // Create the MutRef[$$T] param.
        static auto mutRefParam = ValueToEIR( ToValue( TNamedDecl(
            ValueToEIR( ToDeclValue( ReferenceType{ TTVarT, MutAccessSpecifer(), } ) ), "ref"_sid ) ) );

        auto initValParam = ValueToEIR( ToValue( Decl( initVal.type(), "initVal"_sid ) ) );

        // Create the _ ( MutRef[$$T], initType ) initFunc param.
        auto initFuncTFTParam = ValueToEIR( ToValue(
            TNamedDecl( ValueToEIR( ToValue( TFuncType( TVarAny, VEC( move( mutRefParam ), move( initValParam ) ) ) ) ),
                "initFunc"_sid ) ) );

        TemplateContext tc( c );

        // Create our parameter list.
        auto paramPat = VEC(
            *BuildTemplateSignature( tc, TTVarT ),
            *BuildTemplateSignature( tc, initFuncTFTParam )
        );

        // Create our arg list.
        auto args = VEC(
            *BuildTemplateArgPattern( c, typeTExpr ),
            ValueToEIR( ToValue( c.env()->extInitialize() ) )
        );

        auto us = FindBestTyping( paramPat, args, c );

        if( holds_alternative< NoUnification >( us ) )
        {
            // TODO display details
            DiagnosticsManager::GetInstance().emitErrorMessage( 0,
                "variable initialization type mismatch." );
            return PoisonValue();
        }


        if( holds_alternative< AmbiguousTypeCheck >( us ) )
        {
            // TODO display details
            DiagnosticsManager::GetInstance().emitErrorMessage( 0,
                "ambiguous variable type inference." );
            return PoisonValue();
        }

        auto&& [s,tcc] = get< TCSol >( us );

        // Perform the setup of the type template expression. This will create local bindings
        // for tvars ($whatever), if any, making them available for further use.

        // We need to create a temporary context and adjust the identity so that the tvar
        // bindings will be injected to our parent scope, rather than in our local statement scope.
        auto parentIdentity = TakeVectorTerm( c.identity(), VecSize( c.identity() ) - 2 );
        Context ctxt( c.env(), parentIdentity );

        // The TVar setup expects to find its name on the left hand side of the type checking,
        // But in our case we have put it on the rhs, so we need to flip the context around
        // before setup.
        TemplateSetup( ctxt, tcc.flip(), typeTExpr );

        auto callDecomp = Decompose( s,
            Vec(
                SubTerm(),  // locvar
                SubTerm()   // initializer
            )
        );

        auto&& [type, initializer] = *callDecomp;

        if( !ParseTypePredicates( c, *EIRToValue( type ) ) )
            return PoisonValue();

        auto index = util::GenerateNewUID();

        // Retrieve the texpr's location and set it on the inferred type. This way if an
        // error occurs later with it, for instance when calling LowerTypeForRuntime on it during codegen,
        // it will have a meaningful location for the error message to attach itself on.
        auto typeLoc = EIRToValue( typeTExpr )->locationId();
        LocalVar lv( name, type, index );

        LocalVar lv( name, ValueToEIR( type ), index );
        bb->append( AllocVar( type, index, locId ) );
        bb->append( AllocVar( EIRToValue( lv.type() )->setLocationId( typeLoc ), index, locId ) );

        DiagnosticsContext dc( 0, "When invoking Initialize." );

        auto initResult = InvokeOverloadSet( c,
            c.env()->extInitialize(),
            MakeClosedTuple( ToValue( lv ).setLocationId( locId ), initVal ) );