#ifndef EMPATHY_SEMA_UNI_CONTEXT_H
#define EMPATHY_SEMA_UNI_CONTEXT_H
namespace empathy::sema
{
class UnificationContext
{
public:
static constexpr uint32_t InvalidIndex = numeric_limits< uint32_t >::max();
UnificationContext( const ptr< Env >& env );
UnificationContext( ptr< Env >&& env );
const auto& env() const { return m_env; }
const auto& rules() const { return m_env->unificationRuleSet(); }
uint32_t getLHSHoleIndex( const StringId& name ) const;
uint32_t getRHSHoleIndex( const StringId& name ) const;
uint32_t createValue();
void setLHSHoleIndex( const StringId& name, uint32_t index );
void setRHSHoleIndex( const StringId& name, uint32_t index );
const optional< Term >& getValue( uint32_t index ) const
{
assert( m_values.size() > index );
return m_values[index].first;
}
template< typename T >
void setValue( uint32_t index, T&& val, uint32_t complexity )
{
assert( m_values.size() > index );
if( !m_values[index].first )
--m_numUnknownValues;
m_complexity -= m_values[index].second;
m_values = m_values.set( index, { forward< T >( val ), complexity } );
}
UnificationContext& flip()
{
swap( m_currentLHSNamespaceIndex, m_currentRHSNamespaceIndex );
return *this;
}
void incComplexity( uint32_t n = 1 ) { m_complexity += n; }
uint32_t numUnknownValues() const { return m_numUnknownValues; }
uint32_t complexity() const { return m_complexity; }
auto score() const { return UnificationScore( m_complexity, m_pCow->holeDict.size() ); }
// Used to detect and reject recursive hole nesting.
bool isHoleLocked( uint32_t index ) const;
void lockHole( uint32_t index );
void unlockHole( uint32_t index );
private:
ptr< Env > m_env;
using StoredValue = pair< optional< Term >, uint32_t >;
immer::vector< StoredValue > m_values;
uint32_t m_currentLHSNamespaceIndex = 1;
uint32_t m_currentRHSNamespaceIndex = 2;
uint32_t m_numUnknownValues = 0;
uint32_t m_complexity = 0;
using HoleName = pair< StringId, uint32_t >;
struct Cow
{
unordered_map< HoleName, uint32_t > holeDict;
unordered_set< uint32_t > lockedHoles;
};
ptr< Cow > m_pCow = make_shared< Cow >();
};
}
#endif