#include "sema.h"

namespace empathy::sema
{
    Term Substitute( const Term& src, const UnificationContext& context )
    {
        if( !holds_alternative< pvec >( src.content() ) )
            return src;

        auto optHole = HoleFromIRExpr( src );
        if( optHole )
        {
            const auto& hole = *optHole;

            // We only substitute indexed holes. If we encounter a named hole,
            // output it as is.
            if( !holds_alternative< uint32_t >( hole ) )
                return src;

            const auto& optVal = context.getValue( get< uint32_t >( hole ) );
            if( !optVal )
                return src;

            return Substitute( *optVal, context );
        }

        const auto& vec = *get< pvec >( src.content() );
        immer::vector< Term > outputTerms;
        auto vt = outputTerms.transient();
        bool faulty = false;

        for( auto&& t : vec.terms() )
        {
            auto newT = Substitute( t, context );
            faulty = faulty || newT.isFaulty();
            vt.push_back( move( newT ) );
        }

        // TODO: the number of holes in terms is probably not going to end up being useful,
        // so just remove it.
        return Term( src.location(), make_shared< Vector >( vt.persistent(), faulty, 0 ) );
    }
}
