Goose  Artifact [6dc37738a3]

Artifact 6dc37738a38582baf917abf75ceb62020a4fa86dff02321c084a09cbd10947fc:

  • File bs/builtins/types/drop.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: 3610)

#include "builtins/builtins.h"
#include "parse/parse.h"

using namespace goose::parse;
using namespace goose::cir;

namespace goose::builtins
{
    void SetupDropValue( Env& e )
    {
        // Default implementation of DropValue().
        // The cir of computed values with side effects is appended to the current BB of the current parser,
        // all other values are discarded and destroyed.
        RegisterBuiltinFunc< Intrinsic< void ( Value, Value ) > >( e, e.extDropValue(),
            []( const Context& c, const Value& b, const Value& v )
            {
                if( v.isConstant() || !DoesInstrSeqHaveSideEffects( *v.cir() ) )
                {
                    DestroyLiveValue( c, v );
                    return;
                }

                auto cfg = GetCFG( c );
                if( !cfg )
                    return;

                auto bb = cfg->currentBB();
                bb->append( move( *v.cir() ) );
            } );

        using AnyDeclType = CustomPattern< Decl, Decl::Pattern >;

        // DropValue for Decls: declare a local variable with default initialization.
        // TODO: if the invocation to InitializeValue fails, we should have a way to
        // replace the generic "function arguments mismatch" error message with something
        // more specific such as "can't default-initialize a variable of type XXX"
        RegisterBuiltinFunc< Intrinsic< void ( Value, AnyDeclType ) > >( e, e.extDropValue(),
            []( const Context& c, const Value& b, const Value& v )
            {
                if( !GetCFG( c ) )
                {
                    DiagnosticsManager::GetInstance().emitSyntaxErrorMessage( 0, "variable declarations are not allowed here." );
                    return PoisonValue();
                }

                auto decl = *FromValue< Decl >( v );
                return DeclareLocalVar( c, decl.type(), decl.name(), nullopt, v.locationId() );
            } );

        using AnyDeclWithInitType = CustomPattern< DeclWithInit, DeclWithInit::Pattern >;

        // DropValue for DeclWithInit: declare a local variable.
        RegisterBuiltinFunc< Intrinsic< void ( Value, AnyDeclWithInitType ) > >( e, e.extDropValue(),
            []( const Context& c, const Value& b, const Value& v )
            {
                if( !GetCFG( c ) )
                {
                    DiagnosticsManager::GetInstance().emitSyntaxErrorMessage( 0, "variable declarations are not allowed here." );
                    return PoisonValue();
                }

                auto decl = *FromValue< DeclWithInit >( v );
                return DeclareLocalVar( c, decl.type(), decl.name(), decl.init(), decl.declLoc() );
            } );

        using AnyTNamedDeclWithInitType = CustomPattern< TNamedDeclWithInit, TNamedDeclWithInit::Pattern >;

        // DropValue for TNamedDeclWithInit: declare a local variable with local type inference.
        RegisterBuiltinFunc< Intrinsic< void ( Value, AnyTNamedDeclWithInitType ) > >( e, e.extDropValue(),
            []( const Context& c, const Value& b, const Value& v )
            {
               // G_TRACE_VAL( v );
                if( !GetCFG( c ) )
                {
                    DiagnosticsManager::GetInstance().emitSyntaxErrorMessage( 0, "variable declarations are not allowed here." );
                    return PoisonValue();
                }

                auto decl = *FromValue< TNamedDeclWithInit >( v );
                return DeclareLocalVarWithTypeInference( c, decl.type(), decl.name(), decl.init(), decl.declLoc() );
            } );
    }
}