Artifact 8876e002afa84f4c261a119b28921e49950cb1d7c6582b247207f6a38e8f923e:
- File
bs/sema/codebuilder.cpp
— part of check-in
[9b058524b4]
at
2021-02-18 19:35:07
on branch trunk
— Implemented reference initialization, so reference local variables can now be declared, and added a typechecking rule preventing template variables to bind to reference types.
Then fixed a MILLION horrible problems caused by all that. Now almost everything works again. *sobs* (user: achavasse size: 3432)
#include "sema.h" #include "builtins/builtins.h" using namespace goose; using namespace goose::sema; using namespace goose::builtins; bool CodeBuilder::destroyAndPopCurrentLifetimeScopeValues( const Context& c ) { size_t countToPop = 0; for( auto rit = m_liveValuesStack.rbegin(); rit != m_liveValuesStack.rend(); ++rit ) { if( rit->m_lifeTimeScopeLevel < m_lifeTimeScopeLevels ) break; if( !destroyLiveValue( c, rit->m_value ) ) { m_liveValuesStack.clear(); if( cfg() ) cfg()->poison(); return false; } ++countToPop; } m_liveValuesStack.resize( m_liveValuesStack.size() - countToPop ); return true; } bool CodeBuilder::destroyAllLiveValues( const Context& c ) { for( auto rit = m_liveValuesStack.rbegin(); rit != m_liveValuesStack.rend(); ++rit ) { if( !destroyLiveValue( c, rit->m_value ) ) { m_liveValuesStack.clear(); if( cfg() ) cfg()->poison(); return false; } } return true; } bool CodeBuilder::destroyAllLiveValuesFromBreakScope( const Context& c, uint32_t breakScopeLevel ) { for( auto rit = m_liveValuesStack.rbegin(); rit != m_liveValuesStack.rend(); ++rit ) { if( rit->m_breakableScopeLevel < breakScopeLevel ) return true; if( !destroyLiveValue( c, rit->m_value ) ) { m_liveValuesStack.clear(); if( cfg() ) cfg()->poison(); return false; } } return true; } bool CodeBuilder::destroyAllLiveValuesFromContinueScope( const Context& c, uint32_t continueScopeLevel ) { for( auto rit = m_liveValuesStack.rbegin(); rit != m_liveValuesStack.rend(); ++rit ) { if( rit->m_continuableScopeLevel < continueScopeLevel ) return true; if( !destroyLiveValue( c, rit->m_value ) ) { m_liveValuesStack.clear(); if( cfg() ) cfg()->poison(); return false; } } return true; } bool CodeBuilder::destroyLiveValue( const Context& c, const Value& v ) { if( v.isPoison() ) return false; DiagnosticsContext dc( v.locationId(), "When invoking DestroyValue." ); auto result = InvokeOverloadSet( c, c.env()->extDestroyValue(), MakeTuple( v ) ); return !result.isPoison(); } void CodeBuilder::extendValueLifetime( uint32_t index ) { // Find the live value. auto it = find_if( m_liveValuesStack.rbegin(), m_liveValuesStack.rend(), [&]( auto&& lv ) { return lv.m_index == index; } ); if( it == m_liveValuesStack.rend() ) return; --it->m_lifeTimeScopeLevel; // Look for the first value that belongs to the parent lifetime scope, if any. auto last = find_if( it, m_liveValuesStack.rend(), [&]( auto&& lv ) { return lv.m_lifeTimeScopeLevel < it->m_lifeTimeScopeLevel; } ); // We want to remove our value from its current position in the stack // and reinsert it 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. // So we perform a rotation of the stack entries by one place from it to last. rotate( it, it + 1, last ); }