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

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

namespace goose::builtins
{
    void SetupCodeBuilderInterface( Env& e )
    {
        RegisterBuiltinFunc< Eager< void > ( TypeWrapper< ptr< CodeBuilder > > ) >( e, e.extPoisonBuilder(),
            []( const TypeWrapper< ptr< CodeBuilder > >& cb )
            {
                cb->poison();
            } );

        RegisterBuiltinFunc< Eager< bool > ( TypeWrapper< ptr< CodeBuilder > > ) >( e, e.extBuilderAllowsVarDecl(),
            []( const TypeWrapper< ptr< CodeBuilder > >& cb )
            {
                return true;
            } );

        RegisterBuiltinFunc< Eager< TypeWrapper< ptr< cir::CFG > > > ( TypeWrapper< ptr< CodeBuilder > > ) >( e, e.extGetCFG(),
            []( const TypeWrapper< ptr< CodeBuilder > >& cb )
            {
                return cb->cfg();
            } );

        RegisterBuiltinFunc< Eager< uint32_t > ( TypeWrapper< ptr< CodeBuilder > > ) >( e, e.extGetBreakableScopeLevels(),
            []( const TypeWrapper< ptr< CodeBuilder > >& cb )
            {
                return cb->breakableScopeLevels();
            } );

        RegisterBuiltinFunc< Eager< uint32_t > ( TypeWrapper< ptr< CodeBuilder > > ) >( e, e.extGetContinuableScopeLevels(),
            []( const TypeWrapper< ptr< CodeBuilder > >& cb )
            {
                return cb->continuableScopeLevels();
            } );

        RegisterBuiltinFunc< Intrinsic< void ( TypeWrapper< ptr< CodeBuilder > > ) > >( e, e.extBeginVisibilityScope(),
            []( auto&& c, const Value& b )
            {
                auto cb = *FromValue< TypeWrapper< ptr< CodeBuilder > > >( b );
                cb->beginVisibilityScope( c );
            } );

        RegisterBuiltinFunc< Eager< void > ( TypeWrapper< ptr< CodeBuilder > > ) >( e, e.extBeginLifetimeScope(),
            []( const TypeWrapper< ptr< CodeBuilder > >& cb )
            {
                cb->beginLifetimeScope();
            } );

        RegisterBuiltinFunc< Eager< void > ( TypeWrapper< ptr< CodeBuilder > > ) >( e, e.extEndLifetimeScope(),
            []( const TypeWrapper< ptr< CodeBuilder > >& cb )
            {
                cb->endLifetimeScope();
            } );

        RegisterBuiltinFunc< Eager< void > ( TypeWrapper< ptr< CodeBuilder > > ) >( e, e.extBeginBreakableScope(),
            []( const TypeWrapper< ptr< CodeBuilder > >& cb )
            {
                cb->beginBreakableScope();
            } );

        RegisterBuiltinFunc< Eager< void > ( TypeWrapper< ptr< CodeBuilder > > ) >( e, e.extEndBreakableScope(),
            []( const TypeWrapper< ptr< CodeBuilder > >& cb )
            {
                cb->endBreakableScope();
            } );

        RegisterBuiltinFunc< Eager< void > ( TypeWrapper< ptr< CodeBuilder > > ) >( e, e.extBeginContinuableScope(),
            []( const TypeWrapper< ptr< CodeBuilder > >& cb )
            {
                cb->beginContinuableScope();
            } );

        RegisterBuiltinFunc< Eager< void > ( TypeWrapper< ptr< CodeBuilder > > ) >( e, e.extEndContinuableScope(),
            []( const TypeWrapper< ptr< CodeBuilder > >& cb )
            {
                cb->endContinuableScope();
            } );

        RegisterBuiltinFunc< Intrinsic< void ( TypeWrapper< ptr< CodeBuilder > >, Value, uint32_t ) > >( e, e.extDeclareValue(),
            []( auto&& c, const Value& cbv, const Value& v, const Value& index )
            {
                auto cb = *FromValue< TypeWrapper< ptr< CodeBuilder > > >( cbv );
                cb->declareValue( v, *FromValue< uint32_t >( index ) );
            } );

        RegisterBuiltinFunc< Intrinsic< bool ( TypeWrapper< ptr< CodeBuilder > > ) > >( e, e.extDestroyCurrentLifetimeScopeValues(),
            []( auto&& c, const Value& cbv )
            {
                auto cb = *FromValue< TypeWrapper< ptr< CodeBuilder > > >( cbv );
                return ToValue( cb->destroyCurrentLifetimeScopeValues( c ) );
            } );

        RegisterBuiltinFunc< Intrinsic< bool ( TypeWrapper< ptr< CodeBuilder > > ) > >( e, e.extDestroyAllLiveValues(),
            []( auto&& c, const Value& cbv )
            {
                auto cb = *FromValue< TypeWrapper< ptr< CodeBuilder > > >( cbv );
                return ToValue( cb->destroyAllLiveValues( c ) );
            } );

        RegisterBuiltinFunc< Intrinsic< bool ( TypeWrapper< ptr< CodeBuilder > >, uint32_t ) > >( e, e.extDestroyAllLiveValuesFromBreakScope(),
            []( auto&& c, const Value& cbv, const Value& index )
            {
                auto cb = *FromValue< TypeWrapper< ptr< CodeBuilder > > >( cbv );
                return ToValue( cb->destroyAllLiveValuesFromBreakScope( c, *FromValue< uint32_t >( index ) ) );
            } );

        RegisterBuiltinFunc< Intrinsic< bool ( TypeWrapper< ptr< CodeBuilder > >, uint32_t ) > >( e, e.extDestroyAllLiveValuesFromContinueScope(),
            []( auto&& c, const Value& cbv, const Value& index )
            {
                auto cb = *FromValue< TypeWrapper< ptr< CodeBuilder > > >( cbv );
                return ToValue( cb->destroyAllLiveValuesFromContinueScope( c, *FromValue< uint32_t >( index ) ) );
            } );
    }
}
