#include "builtins/builtins.h"

namespace empathy::builtins
{
    bool IsBuiltinFunc( const Value& func )
    {
        auto funcType = ValueFromIRExpr( func.type() );
        assert( funcType );

        auto decomp = Decompose( funcType->val(),
            Vec(
                Lit( "func"_sid ),
                Lit( "builtin"_sid ),
                SubTerm(),  // domain
                SubTerm(),  // return type
                SubTerm()   // param types
            )
        );

        if( decomp )
            return true;

        decomp = Decompose( funcType->val(),
            Vec(
                Lit( "func"_sid ),
                Lit( "builtin_eager"_sid ),
                SubTerm(),  // domain
                SubTerm(),  // return type
                SubTerm()   // param types
            )
        );

        return !!decomp;
    }

    bool IsNonEagerBuiltinFunc( const Value& func )
    {
        auto funcType = ValueFromIRExpr( func.type() );
        assert( funcType );

        auto decomp = Decompose( funcType->val(),
            Vec(
                Lit( "func"_sid ),
                Lit( "builtin"_sid ),
                SubTerm(),  // domain
                SubTerm(),  // return type
                SubTerm()   // param types
            )
        );

        return !!decomp;
    }

    bool IsEagerBuiltinFunc( const Value& func )
    {
        auto funcType = ValueFromIRExpr( func.type() );
        assert( funcType );

        auto decomp = Decompose( funcType->val(),
            Vec(
                Lit( "func"_sid ),
                Lit( "builtin_eager"_sid ),
                SubTerm(),  // domain
                SubTerm(),  // return type
                SubTerm()   // param types
            )
        );

        return !!decomp;
    }

    const BuiltinFuncWrapper& GetBuiltinFuncWrapper( const Value& func )
    {
        assert( IsBuiltinFunc( func ) || IsIntrinsicFunc( func ) );

        const auto& p = get< ptr< void > >( func.val() );
        return *static_pointer_cast< BuiltinFuncWrapper >( p );
    }
}
