#include "builtins/builtins.h"
#include "precedence.h"
#include "helpers.h"
#include "tuple.h"
using namespace goose;
using namespace goose::eir;
using namespace goose::cir;
using namespace goose::parse;
namespace goose::builtins
{
void SetupArithOps( Env& e )
{
BuildParseRule( e, "+"_sid,
PrefixOp( "operator_unary_plus"_sid, precedence::UnaryOps,
BuildGenericTupleOperator(),
ForType< BigInt >( []< typename O >( auto&& c, O&& operand ) -> Value
{
return forward< O >( operand );
} ),
ForType< CustomPattern< IntegerType, IntegerType::Pattern > >(
[]< typename O >( auto&& c, O&& operand ) -> Value
{
return forward< O >( operand );
} )
),
LeftAssInfixOp( "operator_add"_sid, precedence::AddSubOp,
BuildGenericTupleOperator(),
ForType< BigInt, Add >(),
ForType< CustomPattern< IntegerType, IntegerType::Pattern > >(
[]( auto&& c, auto&& lhs, auto&& rhs ) -> Value
{
return BuildComputedValue( lhs.type(),
Add( lhs, rhs ) );
} )
)
);
BuildParseRule( e, "-"_sid,
PrefixOp( "operator_unary_minus"_sid, precedence::UnaryOps,
BuildGenericTupleOperator(),
ForType< BigInt >( []( auto&& c, auto&& operand ) -> Value
{
return BuildComputedValue( GetValueType< BigInt >(),
Sub( ToValue( BigInt() ), operand ) );
} ),
ForType< CustomPattern< IntegerType, IntegerType::PatternSigned > >(
[]( auto&& c, auto&& operand ) -> Value
{
auto opTypeVal = *EIRToValue( operand.type() );
auto opType = *FromValue< IntegerType >( opTypeVal );
return BuildComputedValue( operand.type(),
Sub( Value( operand.type(), APSInt( opType.m_numBits, false ) ),
operand ) );
} )
),
LeftAssInfixOp( "operator_sub"_sid, precedence::AddSubOp,
BuildGenericTupleOperator(),
ForType< BigInt, Sub >(),
ForType< CustomPattern< IntegerType, IntegerType::Pattern > >(
[]( auto&& c, auto&& lhs, auto&& rhs ) -> Value
{
return BuildComputedValue( lhs.type(),
Sub( lhs, rhs ) );
} )
)
);
BuildParseRule( e, "*"_sid,
LeftAssInfixOp( "operator_multiply"_sid, precedence::MulDivOp,
BuildGenericTupleOperator(),
ForType< BigInt, Mul >(),
ForType< CustomPattern< IntegerType, IntegerType::Pattern > >(
[]( auto&& c, auto&& lhs, auto&& rhs ) -> Value
{
return BuildComputedValue( lhs.type(),
Mul( lhs, rhs ) );
} )
)
);
BuildParseRule( e, "/"_sid,
LeftAssInfixOp( "operator_divide"_sid, precedence::MulDivOp,
BuildGenericTupleOperator(),
ForType< BigInt, SDiv >(),
ForType< CustomPattern< IntegerType, IntegerType::PatternSigned > >(
[]( auto&& c, auto&& lhs, auto&& rhs ) -> Value
{
using namespace goose::builtins::exprhelpers;
auto cfg = GetCFG( c );
assert( cfg );
// Build a zero constant of the same type as the denominator
// to construct the assertion expression.
auto zeroValue = Value( rhs.type(), APSInt::get( 0 ) );
auto cond = Neq( rhs, zeroValue );
DiagnosticsManager::GetInstance().defineCustomDiagnostic(
cond.locationId(), "assert"_sid, "the divisor may be 0." );
cfg->currentBB()->emplace_back(
cir::Assert( move( cond ) )
);
return BuildComputedValue( lhs.type(),
SDiv( lhs, rhs ) );
} ),
ForType< CustomPattern< IntegerType, IntegerType::PatternUnsigned > >(
[]( auto&& c, auto&& lhs, auto&& rhs ) -> Value
{
using namespace goose::builtins::exprhelpers;
auto cfg = GetCFG( c );
assert( cfg );
// Build a zero constant of the same type as the denominator
// to construct the assertion expression.
auto zeroValue = Value( rhs.type(), APSInt::get( 0 ) );
auto cond = Neq( rhs, zeroValue );
DiagnosticsManager::GetInstance().defineCustomDiagnostic(
cond.locationId(), "assert"_sid, "the divisor may be 0." );
cfg->currentBB()->emplace_back(
cir::Assert( move( cond ) )
);
return BuildComputedValue( lhs.type(),
UDiv( lhs, rhs ) );
} )
)
);
BuildParseRule( e, "%"_sid,
LeftAssInfixOp( "operator_modulo"_sid, precedence::MulDivOp,
BuildGenericTupleOperator(),
ForType< BigInt, SRem >(),
ForType< CustomPattern< IntegerType, IntegerType::PatternSigned > >(
[]( auto&& c, auto&& lhs, auto&& rhs ) -> Value
{
using namespace goose::builtins::exprhelpers;
auto cfg = GetCFG( c );
assert( cfg );
// Build a zero constant of the same type as the denominator
// to construct the assertion expression.
auto zeroValue = Value( rhs.type(), APSInt::get( 0 ) );
auto cond = Neq( rhs, zeroValue );
DiagnosticsManager::GetInstance().defineCustomDiagnostic(
cond.locationId(), "assert"_sid, "the divisor may be 0." );
cfg->currentBB()->emplace_back(
cir::Assert( move( cond ) )
);
return BuildComputedValue( lhs.type(),
SRem( lhs, rhs ) );
} ),
ForType< CustomPattern< IntegerType, IntegerType::PatternUnsigned > >(
[]( auto&& c, auto&& lhs, auto&& rhs ) -> Value
{
using namespace goose::builtins::exprhelpers;
auto cfg = GetCFG( c );
assert( cfg );
// Build a zero constant of the same type as the denominator
// to construct the assertion expression.
auto zeroValue = Value( rhs.type(), APSInt::get( 0 ) );
auto cond = Neq( rhs, zeroValue );
DiagnosticsManager::GetInstance().defineCustomDiagnostic(
cond.locationId(), "assert"_sid, "the divisor may be 0." );
cfg->currentBB()->emplace_back(
cir::Assert( move( cond ) )
);
return BuildComputedValue( lhs.type(),
URem( lhs, rhs ) );
} )
)
);
}
}