2024-08-11 23:01:38 +02:00
|
|
|
#include "ScopableName.h"
|
|
|
|
|
|
|
|
|
|
#include <fmt/format.h>
|
|
|
|
|
|
|
|
|
|
#include "clib/clib.h"
|
|
|
|
|
|
|
|
|
|
namespace Pol::Bscript::Compiler
|
|
|
|
|
{
|
2026-01-19 08:17:28 +01:00
|
|
|
ScopableName::ScopableName( const ScopeName& scope, std::string name )
|
|
|
|
|
: scope( scope ), name( std::move( name ) )
|
2024-08-11 23:01:38 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-19 08:17:28 +01:00
|
|
|
ScopableName::ScopableName( std::string scope, std::string name )
|
|
|
|
|
: ScopableName( ScopeName( std::move( scope ) ), std::move( name ) )
|
2024-08-11 23:01:38 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ScopableName::global() const
|
|
|
|
|
{
|
|
|
|
|
return scope.global();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string ScopableName::string() const
|
|
|
|
|
{
|
|
|
|
|
return fmt::format( "{}{}{}", scope.string(), scope.global() ? "" : "::", name );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ScopableName::operator<( const ScopableName& other ) const
|
|
|
|
|
{
|
2024-08-14 12:56:36 +02:00
|
|
|
// Check for special equality condition: <nullopt>::Foo == Foo::Foo
|
|
|
|
|
if ( scope.empty() && !other.scope.empty() )
|
|
|
|
|
{
|
|
|
|
|
std::string expectedScope = name + "::" + name;
|
|
|
|
|
if ( stricmp( other.string().c_str(), expectedScope.c_str() ) == 0 )
|
|
|
|
|
{
|
|
|
|
|
// 'this' is considered equal to 'other' for this special case
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if ( !scope.empty() && other.scope.empty() )
|
|
|
|
|
{
|
|
|
|
|
std::string expectedScope = other.name + "::" + other.name;
|
|
|
|
|
if ( stricmp( string().c_str(), expectedScope.c_str() ) == 0 )
|
|
|
|
|
{
|
|
|
|
|
// 'other' is considered equal to 'this' for this special case
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-11 23:01:38 +02:00
|
|
|
// Compare scopes first
|
|
|
|
|
if ( !scope.empty() && !other.scope.empty() )
|
|
|
|
|
{
|
|
|
|
|
int scopeComparison = stricmp( scope.string().c_str(), other.scope.string().c_str() );
|
|
|
|
|
if ( scopeComparison < 0 )
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if ( scopeComparison > 0 )
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if ( !scope.empty() && other.scope.empty() )
|
|
|
|
|
{
|
2024-08-14 12:56:36 +02:00
|
|
|
return false;
|
2024-08-11 23:01:38 +02:00
|
|
|
}
|
|
|
|
|
else if ( scope.empty() && !other.scope.empty() )
|
|
|
|
|
{
|
2024-08-14 12:56:36 +02:00
|
|
|
return true;
|
2024-08-11 23:01:38 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-14 12:56:36 +02:00
|
|
|
// If scopes are equal (both empty or both equal), compare names
|
2024-08-11 23:01:38 +02:00
|
|
|
return stricmp( name.c_str(), other.name.c_str() ) < 0;
|
|
|
|
|
}
|
|
|
|
|
} // namespace Pol::Bscript::Compiler
|
2024-08-14 12:56:36 +02:00
|
|
|
|
|
|
|
|
fmt::format_context::iterator fmt::formatter<Pol::Bscript::Compiler::ScopableName>::format(
|
|
|
|
|
const Pol::Bscript::Compiler::ScopableName& scoped_name, fmt::format_context& ctx ) const
|
|
|
|
|
{
|
|
|
|
|
// Uses .empty() vs .global() to distinguish "::foo" vs "foo".
|
|
|
|
|
return fmt::formatter<std::string>::format(
|
|
|
|
|
fmt::format( "{}{}{}", scoped_name.scope.string(),
|
|
|
|
|
scoped_name.scope.empty() ? "" : "::", scoped_name.name ),
|
|
|
|
|
ctx );
|
2026-01-19 08:17:28 +01:00
|
|
|
}
|