#include "builtins/builtins.h"

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

namespace empathy::builtins
{
    void SetupLocalVarUnification( Env& e )
    {
        auto localVarPattern = GetValueType< LocalVar >( ANYTERM( _ ) );

        // LocalVar unification against a param:
        // Unify the contained value with the param.
        e.unificationRuleSet()->addAsymRule(

            ValueToIRExpr( ValuePattern(
                ANYTERM( _ ),
                ANYTERM( _ ),
                ANYTERM( _ ) ) ),

            ValueToIRExpr( ValuePattern(
                ANYTERM( _ ),
                localVarPattern,
                ANYTERM( _ ) ) ),

        []( const Term& lhs, const Term& rhs, UnificationContext& c ) -> UniGen
        {
            auto locvar = FromValue< LocalVar >( *ValueFromIRExpr( rhs ) );
            if( !locvar )
                co_return;

            auto varcontent = ValueToIRExpr( BuildComputedValue( locvar->type(),
                GetVar( locvar->cfgId(), locvar->index() ) ) );

            // Unify the param with the var's content
            co_yield Unify( lhs, varcontent, c );
        } );

        // LocalVar unification against another LocalVar: unify their types.
        e.unificationRuleSet()->addAsymRule(

            ValueToIRExpr( ValuePattern(
                ANYTERM( _ ),
                localVarPattern,
                ANYTERM( _ ) ) ),

            ValueToIRExpr( ValuePattern(
                ANYTERM( _ ),
                localVarPattern,
                ANYTERM( _ ) ) ),

        []( const Term& lhs, const Term& rhs, UnificationContext& c ) -> UniGen
        {
            auto lvarType = *FromValue< LocalVarType >( *ValueFromIRExpr( ValuePatternFromIRExpr( lhs )->type() ) );
            auto rvar = *FromValue< LocalVar >( *ValueFromIRExpr( rhs ) );

            for( auto&& [s, uc] : Unify( lvarType.type(), rvar.type(), c ) )
                co_yield { ValueToIRExpr( ToValue( LocalVar( s, rvar.cfgId(), rvar.index() ) ) ), uc };
        } );
    }
}
