Files
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

218 lines
7.5 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "uLang/Semantics/Definition.h"
#include "uLang/Semantics/DataDefinition.h"
#include "uLang/Common/Text/UTF8String.h"
#include "uLang/Semantics/SemanticProgram.h"
#include "uLang/Semantics/SemanticScope.h"
#include "uLang/Semantics/SemanticTypes.h"
namespace uLang
{
SQualifier SQualifier::GetConstrainedQualifier() const
{
if (_Type == EType::NominalType)
{
const CDefinition* ConstrainedDefinition = U._NominalType->Definition()->GetConstrainedDefinition();
ULANG_ASSERT(ConstrainedDefinition);
const CLogicalScope* ConstrainedLogicalScope = ConstrainedDefinition->DefinitionAsLogicalScopeNullable();
ULANG_ASSERT(ConstrainedLogicalScope);
const CTypeBase* ConstrainedType = ConstrainedLogicalScope->ScopeAsType();
ULANG_ASSERT(ConstrainedType);
const CNominalType* ConstrainedNominalType = ConstrainedType->GetNormalType().AsNominalType();
ULANG_ASSERT(ConstrainedNominalType);
return SQualifier::NominalType(ConstrainedNominalType);
}
if (_Type == EType::LogicalScope)
{
const CDefinition* Definition = U._LogicalScope->ScopeAsDefinition();
ULANG_ASSERT(Definition);
const CDefinition* ConstrainedDefinition = Definition->GetConstrainedDefinition();
ULANG_ASSERT(ConstrainedDefinition);
const CLogicalScope* ConstrainedLogicalScope = ConstrainedDefinition->DefinitionAsLogicalScopeNullable();
ULANG_ASSERT(ConstrainedLogicalScope);
return SQualifier::LogicalScope(ConstrainedLogicalScope);
}
return *this;
}
CDefinition::CDefinition(EKind Kind, CScope& EnclosingScope, const CSymbol& Name)
: CNamed(Name)
, _EnclosingScope(EnclosingScope)
, _ParentScopeOrdinal(EnclosingScope.GetLogicalScope().AllocateNextDefinitionOrdinal())
, _Qualifier{SQualifier::Unknown()}
, _Kind(Kind)
{
EnclosingScope.GetProgram()._SymbolMap.FindOrInsert(Name)._Value.Add(this);
}
CDefinition::~CDefinition()
{
// Hack to allow CDefinition to reference a default expression for a non CExprDataDefinition named argument.
// @JIRA SOL-2695 Named parameter needs to detach double link with AST
//ULANG_ASSERTF(!GetAstNode(), "Expected %s definition AST node link to be cleared before definition is destroyed", DefinitionKindAsCString(GetKind()));
//ULANG_ASSERTF(!GetIrNode(true), "Expected %s definition IR node link to be cleared before definition is destroyed", DefinitionKindAsCString(GetKind()));
}
const CDefinition& CDefinition::GetBaseClassOverriddenDefinition() const
{
const CDefinition* BaseOverriddenDefinition = this;
while (BaseOverriddenDefinition->GetOverriddenDefinition() != nullptr && BaseOverriddenDefinition->GetOverriddenDefinition()->_EnclosingScope.GetKind() != CScope::EKind::Interface)
{
BaseOverriddenDefinition = BaseOverriddenDefinition->GetOverriddenDefinition();
}
return *BaseOverriddenDefinition;
}
SAccessLevel CDefinition::DerivedAccessLevel() const
{
const CDefinition& DefinitionAccessibilityRoot = GetDefinitionAccessibilityRoot();
if (DefinitionAccessibilityRoot._AccessLevel.IsSet())
{
return DefinitionAccessibilityRoot._AccessLevel.GetValue();
}
else
{
return DefinitionAccessibilityRoot._EnclosingScope.GetDefaultDefinitionAccessLevel();
}
}
bool CDefinition::IsInstanceMember() const
{
return _EnclosingScope.GetKind() == CScope::EKind::Class
|| _EnclosingScope.GetKind() == CScope::EKind::Interface;
}
bool CDefinition::IsDeprecated() const
{
return HasAttributeClass(_EnclosingScope.GetProgram()._deprecatedClass, _EnclosingScope.GetProgram());
}
bool CDefinition::IsExperimental() const
{
return HasAttributeClass(_EnclosingScope.GetProgram()._experimentalClass, _EnclosingScope.GetProgram());
}
bool CDefinition::IsFinal() const
{
return HasAttributeClass(_EnclosingScope.GetProgram()._finalClass, _EnclosingScope.GetProgram());
}
const CExpressionBase* CDefinition::GetNativeSpecifierExpression() const
{
return FindAttributeExpr(_EnclosingScope.GetProgram()._nativeClass, _EnclosingScope.GetProgram());
}
bool CDefinition::IsNative() const
{
return GetNativeSpecifierExpression() != nullptr;
}
bool CDefinition::IsBuiltIn() const
{
return _EnclosingScope.IsBuiltInScope();
}
CUTF8String GetQualifiedNameString(const CDefinition& Definition)
{
return CUTF8String("(%s:)%s", Definition._EnclosingScope.GetScopePath('/', CScope::EPathMode::PrefixSeparator).AsCString(), Definition.AsNameCString());
}
CUTF8String GetCrcNameString(const CDefinition& Definition)
{
if (Definition.GetKind() == CDefinition::EKind::Data && Definition._EnclosingScope.GetKind() == uLang::CScope::EKind::Interface)
{
return GetQualifiedNameString(Definition);
}
else
{
return Definition.AsNameCString();
}
}
const char* DefinitionKindAsCString(CDefinition::EKind Kind)
{
switch(Kind)
{
#define VISIT_KIND(Name, String) case CDefinition::EKind::Name: return String;
VERSE_ENUM_DEFINITION_KINDS(VISIT_KIND)
#undef VISIT_KIND
default: ULANG_UNREACHABLE();
};
}
bool CDefinition::IsAccessibleFrom(const CScope& Scope) const
{
const CDefinition& Definition = GetDefinitionAccessibilityRoot();
return Scope.CanAccess(Definition, Definition.DerivedAccessLevel());
}
const CDefinition* CDefinition::GetEnclosingDefinition() const
{
for (const CScope* Scope = &_EnclosingScope; Scope; Scope = Scope->GetParentScope())
{
if (const CDefinition* EnclosingScopeDefinition = Scope->ScopeAsDefinition())
{
return EnclosingScopeDefinition;
}
}
return nullptr;
}
bool CDefinition::IsExplicitlyLocallyQualified() const
{
return _Qualifier._Type == SQualifier::EType::Local;
}
bool CDefinition::IsLocallyQualified() const
{
// If it's explicitly `(local:)`-qualified, it's still local.
if (IsExplicitlyLocallyQualified())
{
return true;
}
// Anything within a function local-scope and which isn't explicitly-qualified
// is implicitly `(local:)`.
return _Qualifier._Type == SQualifier::EType::Unknown && _EnclosingScope.GetScopeOfKind(CScope::EKind::Function) != nullptr;
}
SQualifier CDefinition::GetImplicitQualifier() const
{
const CDefinition& BaseDefinition = GetBaseOverriddenDefinition();
return BaseDefinition._EnclosingScope.GetLogicalScope().AsQualifier();
}
void CDefinition::SetName(const CSymbol& NewName)
{
const CSymbol& OldName = GetName();
if (CLogicalScope* EnclosingLogicalScope = _EnclosingScope.AsLogicalScopeNullable())
{
// Renaming a definition requires that we reindex it into the Name map.
if (SmallDefinitionArray* ScopeDefinitions = EnclosingLogicalScope->GetDefinitionNameMap().Find(OldName))
{
ScopeDefinitions->Remove(this);
if (ScopeDefinitions->IsEmpty())
{
EnclosingLogicalScope->GetDefinitionNameMap().Remove(OldName);
}
}
EnclosingLogicalScope->GetDefinitionNameMap().FindOrInsert(NewName)._Value.Add(this);
}
// Update the program-wide CSymbol->Definition map
if (SSymbolDefinitionArray* SymbolDefinitions = _EnclosingScope.GetProgram()._SymbolMap.Find(OldName))
{
SymbolDefinitions->Remove(this);
if (SymbolDefinitions->IsEmpty())
{
_EnclosingScope.GetProgram()._SymbolMap.Remove(OldName);
}
}
_EnclosingScope.GetProgram()._SymbolMap.FindOrInsert(NewName)._Value.Add(this);
_Name = NewName;
}
} // namespace uLang