#include "eir.h"

namespace goose::eir
{
    bool operator==( const Term& lhs, const Term& rhs )
    {
        if( lhs.index() != rhs.index() )
            return false;

        return visit(
            [&]< typename T >( const T& l )
            {
                const auto& r = get< T >( rhs );

                if constexpr( is_same_v< pvec, T > )
                    return *l == *r;
                else if constexpr( is_same_v< LocationId, T > )
                    return true;
                else if constexpr( is_same_v< ptr< void >, T > )
                    return true;
                else if constexpr( is_same_v< void*, T > )
                    return true;
                else if constexpr( is_same_v< APSInt, T > )
                    return l.isSigned() == r.isSigned() && l.getBitWidth() == r.getBitWidth()
                        && l == r;
                else
                    return l == r;
            },
            lhs );
    }

    bool operator!=( const Term& lhs, const Term& rhs )
    {
        return !( lhs == rhs );
    }

    bool Vector::operator==( const Vector& rhs ) const
    {
        return m_repetitionTerm == rhs.m_repetitionTerm && m_terms == rhs.m_terms;
    }

    bool Hole::operator<( const Hole& rhs ) const
    {
        if( name() != rhs.name() )
            return name() < rhs.name();

        if( behavior() != rhs.behavior() )
            return behavior() < rhs.behavior();

        return kind() < rhs.kind();
    }

    bool Hole::operator==( const Hole& rhs ) const
    {
        return name() == rhs.name() && behavior() == rhs.behavior() && kind() == rhs.kind();
    }
} // namespace goose::eir
