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

using namespace goose::parse;
using namespace goose::llr;

namespace goose::builtins
{
    void SetupDropValue( Env& e )
    {
        // Default implementation of DropValue().
        // Constant values are discarded, and the llr of computed values
        // is appended to the current BB of the current parser.
        RegisterBuiltinFunc< Intrinsic< void ( Value ) > >( e, e.extDropValue(),
            []( const Value& v )
            {
                if( v.isConstant() )
                    return;

                auto& p = *Parser::GetCurrentParser();
                auto bb = p.cfg()->currentBB();
                bb->emplace_back( move( *v.llr() ) );
            } );

        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 ( AnyDeclType ) > >( e, e.extDropValue(),
            []( const Value& v )
            {
                auto& p = *Parser::GetCurrentParser();

                if( !p.cfg() )
                {
                    DiagnosticsManager::GetInstance().emitSyntaxErrorMessage( 0, "variable declarations are not allowed here." );
                    return PoisonValue();
                }

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