#include "builtins/builtins.h"
#include "precedence.h"
#include "helpers.h"

using namespace empathy;
using namespace empathy::ir;
using namespace empathy::llr;
using namespace empathy::parse;

namespace empathy::builtins
{
    void SetupComparisonOps( Env& e )
    {
        BuildParseRule( e, "=="_sid,
            LeftAssInfixOp( "operator_equals"_sid, precedence::EqualityOp,
                ForType< bool, Eq >(),
                ForType< BigInt, Eq >(),
                ForType< string, Eq >(),
                ForType< CustomPattern< IntegerType, IntegerType::Pattern > >(
                []( auto&& lhs, auto&& rhs ) -> Value
                {
                    return BuildComputedValue( lhs.type(),
                        Eq( lhs, rhs ) );
                } )
            )
        );

        BuildParseRule( e, "!="_sid,
            LeftAssInfixOp( "operator_not_equals"_sid, precedence::EqualityOp,
                ForType< bool, Neq >(),
                ForType< BigInt, Neq >(),
                ForType< string, Neq >(),
                ForType< CustomPattern< IntegerType, IntegerType::Pattern > >(
                []( auto&& lhs, auto&& rhs ) -> Value
                {
                    return BuildComputedValue( lhs.type(),
                        Neq( lhs, rhs ) );
                } )
            )
        );

        BuildParseRule( e, ">"_sid,
            LeftAssInfixOp( "operator_greater"_sid, precedence::GreaterLesserOp,
                ForType< BigInt, SGT >(),
                ForType< CustomPattern< IntegerType, IntegerType::PatternSigned > >(
                []( auto&& lhs, auto&& rhs ) -> Value
                {
                    return BuildComputedValue( lhs.type(),
                        SGT( lhs, rhs ) );
                } ),
                ForType< CustomPattern< IntegerType, IntegerType::PatternUnsigned > >(
                []( auto&& lhs, auto&& rhs ) -> Value
                {
                    return BuildComputedValue( lhs.type(),
                        UGT( lhs, rhs ) );
                } )
            )
        );

        BuildParseRule( e, ">="_sid,
            LeftAssInfixOp( "operator_greater_or_equals"_sid, precedence::GreaterLesserOp,
                ForType< BigInt, SGE >(),
                ForType< CustomPattern< IntegerType, IntegerType::PatternSigned > >(
                []( auto&& lhs, auto&& rhs ) -> Value
                {
                    return BuildComputedValue( lhs.type(),
                        SGE( lhs, rhs ) );
                } ),
                ForType< CustomPattern< IntegerType, IntegerType::PatternUnsigned > >(
                []( auto&& lhs, auto&& rhs ) -> Value
                {
                    return BuildComputedValue( lhs.type(),
                        UGE( lhs, rhs ) );
                } )
            )
        );

        BuildParseRule( e, "<"_sid,
            LeftAssInfixOp( "operator_lesser"_sid, precedence::GreaterLesserOp,
                ForType< BigInt, SLT >(),
                ForType< CustomPattern< IntegerType, IntegerType::PatternSigned > >(
                []( auto&& lhs, auto&& rhs ) -> Value
                {
                    return BuildComputedValue( lhs.type(),
                        SLT( lhs, rhs ) );
                } ),
                ForType< CustomPattern< IntegerType, IntegerType::PatternUnsigned > >(
                []( auto&& lhs, auto&& rhs ) -> Value
                {
                    return BuildComputedValue( lhs.type(),
                        ULT( lhs, rhs ) );
                } )
            )
        );

        BuildParseRule( e, "<="_sid,
            LeftAssInfixOp( "operator_lesser_or_equals"_sid, precedence::GreaterLesserOp,
                ForType< BigInt, SLE >(),
                ForType< CustomPattern< IntegerType, IntegerType::PatternSigned > >(
                []( auto&& lhs, auto&& rhs ) -> Value
                {
                    return BuildComputedValue( lhs.type(),
                        SLE( lhs, rhs ) );
                } ),
                ForType< CustomPattern< IntegerType, IntegerType::PatternUnsigned > >(
                []( auto&& lhs, auto&& rhs ) -> Value
                {
                    return BuildComputedValue( lhs.type(),
                        ULE( lhs, rhs ) );
                } )
            )
        );
    }
}
