#ifndef GOOSE_BUILTINS_BUILDERS_LIFECYCLE_MANAGER_INL
#define GOOSE_BUILTINS_BUILDERS_LIFECYCLE_MANAGER_INL
namespace goose::builtins
{
template< class C >
void LifeCycleManager< C >::endLifetimeScope( Context& c )
{
destroyCurrentLifetimeScopeValues( c );
--m_lifetimeScopeLevels;
}
template< class C >
void LifeCycleManager< C >::destroyCurrentLifetimeScopeValues( const Context& c )
{
auto it = m_liveValuesList.begin();
while( it != m_liveValuesList.end() )
{
if( it->m_lifetimeScopeLevel < m_lifetimeScopeLevels )
break;
if( !destroyLiveValue( c, it->m_value ) )
{
m_liveValuesList.clear();
crtp().poison();
return;
}
it = m_liveValuesList.erase( it );
}
}
template< class C >
bool LifeCycleManager< C >::destroyAllLiveValues( const Context& c )
{
for( auto it = m_liveValuesList.begin(); it != m_liveValuesList.end(); ++it )
{
if( !destroyLiveValue( c, it->m_value ) )
{
m_liveValuesList.clear();
crtp().poison();
return false;
}
}
return true;
}
template< class C >
bool LifeCycleManager< C >::destroyAllLiveValuesFromBreakScope( const Context& c, uint32_t breakScopeLevel )
{
for( auto it = m_liveValuesList.begin(); it != m_liveValuesList.end(); ++it )
{
if( it->m_breakableScopeLevel < breakScopeLevel )
return true;
if( !destroyLiveValue( c, it->m_value ) )
{
m_liveValuesList.clear();
crtp().poison();
return false;
}
}
return true;
}
template< class C >
bool LifeCycleManager< C >::destroyAllLiveValuesFromContinueScope( const Context& c, uint32_t continueScopeLevel )
{
for( auto it = m_liveValuesList.begin(); it != m_liveValuesList.end(); ++it )
{
if( it->m_continuableScopeLevel < continueScopeLevel )
return true;
if( !destroyLiveValue( c, it->m_value ) )
{
m_liveValuesList.clear();
crtp().poison();
return false;
}
}
return true;
}
template< class C >
bool LifeCycleManager< C >::destroyLiveValue( const Context& c, const Value& v, source_location sloc )
{
if( v.isPoison() )
{
crtp().poison();
return false;
}
DiagnosticsContext dc( v.locationId(), "When invoking DestroyValue." );
auto result = InvokeOverloadSet( c, c.env()->extDestroyValue(),
MakeClosedTuple( v ), Location::Create( sloc ) );
if( result.isPoison() )
{
crtp().poison();
return false;
}
if( !result.isConstant() )
crtp().append( move( result ) );
return true;
}
template< class C >
void LifeCycleManager< C >::extendValueLifetime( uint32_t index )
{
// Find the live value.
auto it = find_if( m_liveValuesList.begin(), m_liveValuesList.end(),
[&]( auto&& lv )
{
return lv.m_index == index;
} );
if( it == m_liveValuesList.end() )
return;
--it->m_lifetimeScopeLevel;
// Look for the last value that belongs to the parent lifetime scope, if any.
auto last = find_if( it, m_liveValuesList.end(),
[&]( auto&& lv )
{
return lv.m_lifetimeScopeLevel < it->m_lifetimeScopeLevel;
} );
// Reinsert the value just after the last value of the parent scope (the one we
// just found), like it would be if it was inserted in that lifetime scope in the first
// place.
auto lvToExtend = move( *it );
m_liveValuesList.erase( it );
m_liveValuesList.emplace( last, move( lvToExtend ) );
}
}
#endif