#include "sema.h"
using namespace goose;
using namespace goose::sema;
uint32_t TypeCheckingContext::SubContext::repetitionIndex( uint32_t depth ) const
{
if( !m_repetitionIndices || m_repetitionIndices->size() <= depth )
return 0;
return ( *m_repetitionIndices )[depth];
}
void TypeCheckingContext::SubContext::setRepetitionIndex( uint32_t depth, uint32_t index )
{
if( !m_repetitionIndices )
m_repetitionIndices = make_shared< RepIndicesVec >();
auto& indices = CoW( m_repetitionIndices );
if( indices->size() <= depth )
indices->resize( depth + 1 );
( *indices )[depth] = index;
}
TypeCheckingContext::TypeCheckingContext( const Context& c ) :
m_context( c )
{}
TypeCheckingContext::TypeCheckingContext( Context&& c ) :
m_context( move( c ) )
{}
uint32_t TypeCheckingContext::getLHSHoleIndex( StringId name, uint32_t repetitionIndex ) const
{
if( name == "_"_sid )
return InvalidIndex;
HoleKey holeKey( name, LHSSubContext().namespaceIndex, repetitionIndex );
auto it = m_pCow->holeDict.find( holeKey );
if( it == m_pCow->holeDict.end() )
return InvalidIndex;
return it->second;
}
uint32_t TypeCheckingContext::getRHSHoleIndex( StringId name, uint32_t repetitionIndex ) const
{
if( name == "_"_sid )
return InvalidIndex;
HoleKey holeKey( name, RHSSubContext().namespaceIndex, repetitionIndex );
auto it = m_pCow->holeDict.find( holeKey );
if( it == m_pCow->holeDict.end() )
return InvalidIndex;
return it->second;
}
uint32_t TypeCheckingContext::createValue( bool required )
{
CoW( m_pCow )->values.emplace_back( StoredValue{ nullopt, required } );
uint32_t index = m_pCow->values.size() - 1;
if( required )
++m_numUnknownValues;
return index;
}
void TypeCheckingContext::setValueRequired( uint32_t index )
{
assert( m_pCow->values.size() > index );
if( m_pCow->values[index].m_required )
return;
CoW( m_pCow )->values[index] = { m_pCow->values[index].m_term, true };
if( !m_pCow->values[index].m_term )
++m_numUnknownValues;
}
void TypeCheckingContext::setLHSHoleIndex( StringId name, uint32_t repetitionIndex, uint32_t index )
{
if( name == "_"_sid )
{
++m_numAnonymousHoles;
return;
}
HoleKey holeKey( name, LHSSubContext().namespaceIndex, repetitionIndex );
CoW( m_pCow )->holeDict.emplace( holeKey, index );
if( m_valuesAreRequired )
setValueRequired( index );
}
void TypeCheckingContext::setRHSHoleIndex( StringId name, uint32_t repetitionIndex, uint32_t index )
{
if( name == "_"_sid )
{
++m_numAnonymousHoles;
return;
}
HoleKey holeKey( name, RHSSubContext().namespaceIndex, repetitionIndex );
CoW( m_pCow )->holeDict.emplace( holeKey, index );
if( m_valuesAreRequired )
setValueRequired( index );
}
void TypeCheckingContext::eraseLHSName( StringId name )
{
HoleKey holeKeyMin( name, LHSSubContext().namespaceIndex, 0 );
HoleKey holeKeyMax( name, LHSSubContext().namespaceIndex, ~0 );
auto begin = CoW( m_pCow )->holeDict.lower_bound( holeKeyMin );
auto end = CoW( m_pCow )->holeDict.upper_bound( holeKeyMax );
CoW( m_pCow )->holeDict.erase( begin, end );
}
void TypeCheckingContext::eraseRHSName( StringId name )
{
HoleKey holeKeyMin( name, RHSSubContext().namespaceIndex, 0 );
HoleKey holeKeyMax( name, RHSSubContext().namespaceIndex, ~0 );
auto begin = CoW( m_pCow )->holeDict.lower_bound( holeKeyMin );
auto end = CoW( m_pCow )->holeDict.upper_bound( holeKeyMax );
CoW( m_pCow )->holeDict.erase( begin, end );
}
bool TypeCheckingContext::isHoleLocked( uint32_t index ) const
{
return m_pCow->lockedHoles.find( index ) != m_pCow->lockedHoles.end();
}
void TypeCheckingContext::lockHole( uint32_t index )
{
CoW( m_pCow )->lockedHoles.emplace( index );
}
void TypeCheckingContext::unlockHole( uint32_t index )
{
CoW( m_pCow )->lockedHoles.erase( index );
}
#ifndef NDEBUG
void TypeCheckingContext::TCRuleTrace( const TCRuleInfo* pRule ) const
{
CoW( m_pCow )->currentTypeCheckingTrace.emplace_back( pRule );
}
void TypeCheckingContext::PushRuleTraceForParam() const
{
auto* pCow = CoW( m_pCow ).get();
pCow->paramsTypeCheckingTrace.emplace_back( move( pCow->currentTypeCheckingTrace ) );
}
void TypeCheckingContext::DumpParamsTraces( ostream& out ) const
{
uint32_t i = 0;
for( auto&& x : m_pCow->paramsTypeCheckingTrace )
{
out << "== TypeChecking trace for param #" << i++ << endl;
for( auto&& y : x )
cout << " " << y->pFilename << ':' << y->line << endl;
}
}
#endif