polserver/pol-core/bscript/compiler/analyzer/Variables.cpp
turleypol fb3faddeae
use c++20 (#799)
* use c++20
* increased used clang version
* compiler report and logfacility use now compile time formatting, which
means that the formatstring gets checked at compile time. (which found 2 errors)
adapted a few places since report only accepts formatting arguments
adapted a few places with logging since char[] is compile time
formatting and string or chr* is runtime formatting
* use std::ranges instead of boost
* disabled pragma_assume vs specific macro (I guess noone cares)
* needed to fix ancient ms exception code
* modernized SpinLock
* removed unused code in ECompile
* replaced std::filesystem::path::u8string with string. It now returns an actual u8string type
* cleanup layers.h added the defines for other layers which where before
  only defined in the pkt
* osmod::OpenConnection and HTTPRequest cleanup: early outs, dont check for pChild which is
  only needed for startscript and placed suspend at the very last
  position

* fix warning

* rebuild cache with new compiler version

* define c++ standard for external libs where possible

* added fixme
2025-08-01 21:40:10 +02:00

120 lines
3.9 KiB
C++

#include "Variables.h"
#include <ranges>
#include "bscript/compiler/Report.h"
#include "bscript/compiler/file/SourceLocation.h"
#include "bscript/compiler/model/Variable.h"
namespace Pol::Bscript::Compiler
{
Variables::Variables( VariableScope scope, Report& report )
: scope( scope ), report( report ), variable_info_stack( { VariablesInfo() } )
{
}
std::shared_ptr<Variable> Variables::create( const std::string& name, BlockDepth block_depth,
WarnOn warn_on, const SourceLocation& source_location )
{
auto index = current().names_by_index.size();
if ( index > std::numeric_limits<VariableIndex>::max() )
{
report.error( source_location, "Too many variables" );
}
auto variable =
std::make_shared<Variable>( scope, name, block_depth, static_cast<VariableIndex>( index ),
warn_on, nullptr, source_location );
current().variables_by_name[name] = variable;
current().names_by_index.push_back( name );
return variable;
}
std::shared_ptr<Variable> Variables::capture( std::shared_ptr<Variable>& other )
{
// The new variable "local variable" representing the capture at runtime have
// consecutive indexes.
// At compilation:
// - Keep track of the current executing function
// - When visiting an identifier:
// - If type == Capture: ValueStack offset will be current function's param count + this variable
// index
// - If type == Local: if offset > function param count, add current function's capture count
auto index = static_cast<VariableIndex>( current().names_by_index.size() );
auto captured =
std::make_shared<Variable>( VariableScope::Capture, other->name, other->block_depth, index,
other->warn_on, other, other->source_location );
current().variables_by_name[other->name] = captured;
current().names_by_index.push_back( captured->name );
return captured;
}
std::shared_ptr<Variable> Variables::find( const std::string& name ) const
{
auto itr = variable_info_stack.back().variables_by_name.find( name );
return ( itr != variable_info_stack.back().variables_by_name.end() )
? ( *itr ).second
: std::shared_ptr<Variable>();
}
std::shared_ptr<Variable> Variables::find_in_ancestors( const std::string& name ) const
{
for ( const auto& info : variable_info_stack | std::views::reverse | std::views::drop( 1 ) )
{
auto itr = info.variables_by_name.find( name );
if ( itr != info.variables_by_name.end() )
{
return ( *itr ).second;
}
}
return nullptr;
}
void Variables::restore_shadowed( std::shared_ptr<Variable> variable )
{
// It's still in names_by_index
current().variables_by_name[variable->name] = std::move( variable );
}
void Variables::remove_all_but( unsigned count )
{
while ( current().names_by_index.size() > count )
{
std::string last_name = current().names_by_index.back();
auto itr = current().variables_by_name.find( last_name );
if ( itr != current().variables_by_name.end() )
{
auto& removing = ( *itr ).second;
if ( removing->warn_on == WarnOn::IfUsed && removing->was_used() )
{
report.warning( removing->source_location,
"local variable '{}' declared as unused but used.", last_name );
}
else if ( removing->warn_on == WarnOn::IfNotUsed && !removing->was_used() )
{
report.warning( removing->source_location, "local variable '{}' was not used.", last_name );
}
current().variables_by_name.erase( itr );
}
current().names_by_index.pop_back();
}
}
const std::vector<std::string>& Variables::get_names() const
{
return variable_info_stack.back().names_by_index;
}
unsigned Variables::count() const
{
return static_cast<unsigned>( variable_info_stack.back().names_by_index.size() );
}
Variables::VariablesInfo& Variables::current()
{
return variable_info_stack.back();
}
} // namespace Pol::Bscript::Compiler