// 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 { CDefinition::CDefinition(EKind Kind, CScope& EnclosingScope, const CSymbol& Name) : CNamed(Name) , _EnclosingScope(EnclosingScope) , _ParentScopeOrdinal(EnclosingScope.GetLogicalScope().AllocateNextDefinitionOrdinal()) , _Qualifier{SQualifier::Unknown()} , _Kind(Kind) {} 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(); } } // namespace uLang