#include "builtins/builtins.h"

using namespace empathy;
using namespace empathy::builtins;

namespace empathy::builtins
{
    void SetupRuntimePointerType( Env& e )
    {
        RegisterBuiltinFunc< Value ( Value ) >( e, "RTPointer"_sid,
            []( const Value& pointedType )
            {
                if( !GetLLVMType( pointedType ) )
                {
                    // TODO come up with some lightweight builtin option type
                    // for the builtin apis, because this is a very bullshit
                    // way to handle errors
                    return ToValue( "error"s );
                }

                return ToValue( RTPointer( ValueToIRExpr( pointedType ) ) );
            } );
    }
}

namespace empathy::ir
{
    Value Bridge< RTPointer >::ToValue( const RTPointer& p )
    {
        return Value( Type(), TVEC( TSID( rt_type ),
            TERM( llvm::PointerType::getUnqual( GetLLVMType( *ValueFromIRExpr( p.m_pointedType ) ) ) ),
            TSID( rt_pointer ), p.m_pointedType ) );
    }

    optional< RTPointer > Bridge< RTPointer >::FromValue( const Value& v )
    {
        auto result = Decompose( v.val(),
            Vec(
                Lit( "rt_type"_sid ),
                Lit( "rt_pointer"_sid ),
                SubTerm()
            )
        );

        if( !result )
            return nullopt;

        auto&& [pointedType] = *result;
        return RTPointer( pointedType );
    }
}
