// 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