#include "sema.h"

using namespace empathy;
using namespace empathy::sema;

UnificationContext::UnificationContext( const ptr< Env >& env ) :
    m_env( env )
{}

UnificationContext::UnificationContext( ptr< Env >&& env ) :
    m_env( move( env ) )
{}

uint32_t UnificationContext::getLHSHoleIndex( const StringId& name ) const
{
    if( name == "_"_sid )
        return InvalidIndex;

    HoleName holeName( name, m_currentLHSNamespaceIndex );

    auto it = m_pCow->holeDict.find( holeName );
    if( it == m_pCow->holeDict.end() )
        return InvalidIndex;

    return it->second;
}

uint32_t UnificationContext::getRHSHoleIndex( const StringId& name ) const
{
    if( name == "_"_sid )
        return InvalidIndex;

    HoleName holeName( name, m_currentRHSNamespaceIndex );

    auto it = m_pCow->holeDict.find( holeName );
    if( it == m_pCow->holeDict.end() )
        return InvalidIndex;

    return it->second;
}

uint32_t UnificationContext::createValue()
{
    m_values = m_values.push_back( { nullopt,0 } );
    uint32_t index = m_values.size() - 1;
    ++m_numUnknownValues;
    return index;
}

void UnificationContext::setLHSHoleIndex( const StringId& name, uint32_t index )
{
    if( name == "_"_sid )
        return;

    HoleName holeName( name, m_currentLHSNamespaceIndex );
    CoW( m_pCow )->holeDict.emplace( holeName, index );
}

void UnificationContext::setRHSHoleIndex( const StringId& name, uint32_t index )
{
    if( name == "_"_sid )
        return;

    HoleName holeName( name, m_currentRHSNamespaceIndex );
    CoW( m_pCow )->holeDict.emplace( holeName, index );
}

bool UnificationContext::isHoleLocked( uint32_t index ) const
{
    return m_pCow->lockedHoles.find( index ) != m_pCow->lockedHoles.end();
}

void UnificationContext::lockHole( uint32_t index )
{
    CoW( m_pCow )->lockedHoles.emplace( index );
}

void UnificationContext::unlockHole( uint32_t index )
{
    CoW( m_pCow )->lockedHoles.erase( index );
}
