#include "builtins/builtins.h"
using namespace goose;
using namespace goose::ir;
namespace goose::builtins
{
void SetupConstrainedFuncUnification( Env& e )
{
auto funcTypePat = ValueToIRExpr( Value( TypeType(), VEC( TSID( func ),
ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );
auto tFuncTypePat = ValueToIRExpr( Value( TypeType(), VEC( TSID( texpr ), TSID( tfunc ),
ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );
// func type param / constrainedfunc arg
e.unificationRuleSet()->addSymRule( URINFOS,
ParamPat( move( funcTypePat ) ),
ValueToIRExpr( ValuePattern(
TSID( constant ),
GetValueType< builtins::ConstrainedFunc >(),
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, UnificationContext& uc ) -> UniGen
{
auto ldecomp = Decompose( lhs,
Vec(
Lit( "value"_sid ),
SubTerm(),
SubTerm(),
SubTerm(),
Val< LocationId >()
)
);
assert( ldecomp );
auto&& [sort, type, val, locId] = *ldecomp;
auto callPat = BuildCallPatternFromFuncType( *ValueFromIRExpr( type ) );
auto rhsVal = *ValueFromIRExpr( rhs );
auto cfunc = FromValue< ConstrainedFunc >( rhsVal );
assert( cfunc );
auto localC = uc;
auto g = Unify( callPat, cfunc->constraintPat(), localC );
auto it = g.begin();
if( it != g.end() )
{
auto func = ValueToIRExpr( cfunc->func() );
co_yield Unify( lhs, func, uc );
}
} );
// tfunc type param / constrainedfunc arg
e.unificationRuleSet()->addAsymRule( URINFOS,
ValueToIRExpr( ValuePattern( HOLE( "_"_sid ), move( tFuncTypePat ), HOLE( "_"_sid ) ) ),
ValueToIRExpr( ValuePattern(
TSID( constant ),
GetValueType< builtins::ConstrainedFunc >(),
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, UnificationContext& uc ) -> UniGen
{
auto ldecomp = Decompose( lhs,
Vec(
Lit( "value"_sid ),
SubTerm(),
SubTerm(),
SubTerm(),
Val< LocationId >()
)
);
assert( ldecomp );
auto&& [sort, type, val, locId] = *ldecomp;
auto callPat = BuildArgPatternFromTFuncType( uc.context(), *ValueFromIRExpr( type ) );
assert( callPat );
auto rhsVal = *ValueFromIRExpr( rhs );
auto cfunc = FromValue< ConstrainedFunc >( rhsVal );
assert( cfunc );
auto localC = uc;
auto g = Unify( *callPat, cfunc->constraintPat(), localC );
auto it = g.begin();
if( it != g.end() )
{
auto func = ValueToIRExpr( cfunc->func() );
co_yield Unify( lhs, func, uc );
}
} );
}
}