Files
UnrealEngine/Engine/Source/Runtime/VerseCompiler/Private/uLang/Semantics/SemanticProgram.cpp
2025-05-18 13:04:45 +08:00

2009 lines
92 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "uLang/Semantics/SemanticProgram.h"
#include "uLang/Common/Algo/AllOf.h"
#include "uLang/Common/Text/FilePathUtils.h"
#include "uLang/Semantics/Expression.h"
#include "uLang/Semantics/MemberOrigin.h"
#include "uLang/Semantics/SmallDefinitionArray.h"
#include "uLang/Semantics/TypeAlias.h"
#include "uLang/Semantics/TypeVariable.h"
#include "uLang/Semantics/VisitStamp.h"
#include "uLang/SourceProject/VerseVersion.h"
#include <initializer_list>
namespace uLang
{
//=======================================================================================
// CModule
//=======================================================================================
CModule::CModule(const CSymbol& Name, CScope& EnclosingScope)
: CDefinition(StaticDefinitionKind, EnclosingScope, Name)
, CNominalType(StaticTypeKind, EnclosingScope.GetProgram())
, CLogicalScope(CScope::EKind::Module, &EnclosingScope, EnclosingScope.GetProgram())
{
}
CModulePart& CModule::CreatePart(CScope* ParentScope, bool bExplicitDefinition)
{
return *_Parts[_Parts.AddNew(*this, ParentScope, bExplicitDefinition, CScope::GetProgram())];
}
bool CModule::IsExplicitDefinition() const
{
// A module definition is explicit if any of its parts was explicitly defined
for (const CModulePart* Part : _Parts)
{
if (Part->IsExplicitDefinition())
{
return true;
}
}
return false;
}
SmallDefinitionArray CModule::FindInstanceMember(const CSymbol& Name, EMemberOrigin Origin, const SQualifier& Qualifier, const CAstPackage* ContextPackage, VisitStampType VisitStamp) const
{
if (TryMarkVisited(VisitStamp))
{
return FindDefinitions(Name, Origin, Qualifier, ContextPackage, VisitStamp);
}
return SmallDefinitionArray();
}
void CModule::MarkPersistenceCompatConstraint() const
{
if (IsPersistenceCompatConstraint())
{
return;
}
_bPersistenceCompatConstraint = true;
if (_Parent)
{
if (const CModule* ParentModule = _Parent->GetModule())
{
ParentModule->MarkPersistenceCompatConstraint();
}
}
}
SmallDefinitionArray CModule::FindDefinitions(const CSymbol& Name, EMemberOrigin Origin, const SQualifier& Qualifier, const CAstPackage* ContextPackage, VisitStampType VisitStamp) const
{
SmallDefinitionArray Definitions = CLogicalScope::FindDefinitions(Name, Origin, Qualifier, ContextPackage, VisitStamp);
if (GetConstrainedDefinition() && Origin != EMemberOrigin::Original)
{
if (const CModule* ConstrainedModule = GetConstrainedDefinition()->AsNullable<CModule>())
{
Definitions.Append(ConstrainedModule->FindDefinitions(Name, Origin, Qualifier, ContextPackage, VisitStamp));
}
}
return Definitions;
}
//=======================================================================================
// CIntrinsicSymbols
//=======================================================================================
void CIntrinsicSymbols::Initialize(CSymbolTable& Symbols)
{
#define OPERATOR_OP_NAME_PREFIX "operator'"
#define PREFIX_OP_NAME_PREFIX "prefix'"
#define POSTFIX_OP_NAME_PREFIX "postfix'"
#define OP_NAME_SUFFIX "'"
#define OPERATOR_OP_NAME(NAME) OPERATOR_OP_NAME_PREFIX #NAME OP_NAME_SUFFIX
#define PREFIX_OP_NAME(NAME) PREFIX_OP_NAME_PREFIX #NAME OP_NAME_SUFFIX
_OperatorOpNamePrefix = OPERATOR_OP_NAME_PREFIX;
_PrefixOpNamePrefix = PREFIX_OP_NAME_PREFIX;
_PostfixOpNamePrefix = POSTFIX_OP_NAME_PREFIX;
_OpNameSuffix = OP_NAME_SUFFIX;
_OpNameNegate = Symbols.AddChecked(PREFIX_OP_NAME(-));
_OpNameAdd = Symbols.AddChecked(OPERATOR_OP_NAME(+));
_OpNameSub = Symbols.AddChecked(OPERATOR_OP_NAME(-));
_OpNameMul = Symbols.AddChecked(OPERATOR_OP_NAME(*));
_OpNameDiv = Symbols.AddChecked(OPERATOR_OP_NAME(/));
_OpNameLess = Symbols.AddChecked(OPERATOR_OP_NAME(<));
_OpNameLessEqual = Symbols.AddChecked(OPERATOR_OP_NAME(<=));
_OpNameGreater = Symbols.AddChecked(OPERATOR_OP_NAME(>));
_OpNameGreaterEqual = Symbols.AddChecked(OPERATOR_OP_NAME(>=));
_OpNameEqual = Symbols.AddChecked(OPERATOR_OP_NAME(=));
_OpNameNotEqual = Symbols.AddChecked(OPERATOR_OP_NAME(<>));
_OpNameAddRMW = Symbols.AddChecked(OPERATOR_OP_NAME(+=));
_OpNameSubRMW = Symbols.AddChecked(OPERATOR_OP_NAME(-=));
_OpNameMulRMW = Symbols.AddChecked(OPERATOR_OP_NAME(*=));
_OpNameDivRMW = Symbols.AddChecked(OPERATOR_OP_NAME(/=));
_OpNameCall = Symbols.AddChecked(OPERATOR_OP_NAME(()));
_OpNameQuery = Symbols.AddChecked(OPERATOR_OP_NAME(?));
#undef OPERATOR_OP_NAME
#undef PREFIX_OP_NAME
#undef OPERATOR_OP_NAME_PREFIX
#undef PREFIX_OP_NAME_PREFIX
#undef POSTFIX_OP_NAME_PREFIX
#undef OP_NAME_SUFFIX
_FuncNameAbs = Symbols.AddChecked("Abs");
_FuncNameCeil = Symbols.AddChecked("Ceil");
_FuncNameFloor = Symbols.AddChecked("Floor");
_FuncNameWeakMap = Symbols.AddChecked("weak_map");
_FuncNameFitsInPlayerMap = Symbols.AddChecked("FitsInPlayerMap");
_FieldNameLength = Symbols.AddChecked("Length");
_Wildcard = Symbols.AddChecked("_");
_Inf = Symbols.AddChecked("Inf");
_NaN = Symbols.AddChecked("NaN");
_ExtensionFieldPrefix = "operator'.";
_ExtensionFieldSuffix = "'";
// @available
_MinUploadedAtFNVersion = Symbols.AddChecked("MinUploadedAtFNVersion");
}
CSymbol CIntrinsicSymbols::GetArithmeticOpName(CExprBinaryArithmetic::EOp Op) const
{
switch (Op)
{
case CExprBinaryArithmetic::EOp::Add: return _OpNameAdd;
case CExprBinaryArithmetic::EOp::Sub: return _OpNameSub;
case CExprBinaryArithmetic::EOp::Mul: return _OpNameMul;
case CExprBinaryArithmetic::EOp::Div: return _OpNameDiv;
default: ULANG_UNREACHABLE();
}
}
CSymbol CIntrinsicSymbols::GetComparisonOpName(CExprComparison::EOp Op) const
{
switch (Op)
{
case CExprComparison::EOp::gt: return _OpNameGreater;
case CExprComparison::EOp::gteq: return _OpNameGreaterEqual;
case CExprComparison::EOp::lt: return _OpNameLess;
case CExprComparison::EOp::lteq: return _OpNameLessEqual;
case CExprComparison::EOp::eq: return _OpNameEqual;
case CExprComparison::EOp::noteq: return _OpNameNotEqual;
default: ULANG_UNREACHABLE();
}
}
CSymbol CIntrinsicSymbols::GetAssignmentOpName(CExprAssignment::EOp Op) const
{
switch (Op)
{
case CExprAssignment::EOp::addAssign: return _OpNameAddRMW;
case CExprAssignment::EOp::subAssign: return _OpNameSubRMW;
case CExprAssignment::EOp::mulAssign: return _OpNameMulRMW;
case CExprAssignment::EOp::divAssign: return _OpNameDivRMW;
case CExprAssignment::EOp::assign: default: ULANG_UNREACHABLE();
}
}
CUTF8String CIntrinsicSymbols::MakeExtensionFieldOpName(CSymbol Symbol) const
{
CUTF8StringBuilder Builder;
Builder.Append(_ExtensionFieldPrefix);
Builder.Append(Symbol.AsStringView());
Builder.Append(_ExtensionFieldSuffix);
return Builder.MoveToString();
}
CUTF8StringView CIntrinsicSymbols::StripExtensionFieldOpName(CSymbol Symbol) const
{
return Symbol.AsStringView()
.SubViewTrimBegin(_ExtensionFieldPrefix.ByteLen())
.SubViewTrimEnd(_ExtensionFieldSuffix.ByteLen());
}
bool CIntrinsicSymbols::IsOperatorOpName(CSymbol Name) const
{
CUTF8StringView View = Name.AsStringView();
return View.StartsWith(_OperatorOpNamePrefix) && View.EndsWith(_OpNameSuffix);
}
bool CIntrinsicSymbols::IsPrefixOpName(CSymbol Name) const
{
CUTF8StringView View = Name.AsStringView();
return View.StartsWith(_PrefixOpNamePrefix) && View.EndsWith(_OpNameSuffix);
}
bool CIntrinsicSymbols::IsPostfixOpName(CSymbol Name) const
{
CUTF8StringView View = Name.AsStringView();
return View.StartsWith(_PostfixOpNamePrefix) && View.EndsWith(_OpNameSuffix);
}
SmallDefinitionArray CCompatConstraintRoot::FindDefinitions(const CSymbol& Name, EMemberOrigin Origin, const SQualifier& Qualifier, const CAstPackage* ContextPackage, VisitStampType VisitStamp) const
{
SmallDefinitionArray Definitions = CLogicalScope::FindDefinitions(Name, Origin, Qualifier, ContextPackage, VisitStamp);
if (Origin != EMemberOrigin::Original)
{
Definitions.Append(GetProgram().FindDefinitions(Name, Origin, Qualifier, ContextPackage, VisitStamp));
}
return Definitions;
}
//=======================================================================================
// CSemanticProgram
//=======================================================================================
void CSemanticProgram::Initialize(TSPtr<CSymbolTable> Symbols)
{
if (!Symbols)
{
// Create default symbol table since a shared one was not provided
_Symbols.SetNew();
}
else
{
_Symbols = Symbols;
}
_IntrinsicSymbols.Initialize(*_Symbols);
ULANG_ASSERTF(_EpicInternalModulePrefixes.IsEmpty(), "`CSemanticProgram` should not be initialized multiple times");
_EpicInternalModulePrefixes.Add("/Verse.org/");
_EpicInternalModulePrefixes.Add("/UnrealEngine.com/");
_EpicInternalModulePrefixes.Add("/Fortnite.com/");
}
const CFunction* CSemanticProgram::GetTaskFunction() const
{
if (!_taskFunction)
{
_taskFunction = FindDefinitionByVersePath<CFunction>("/Verse.org/Concurrency/task");
}
return _taskFunction;
}
const CClass* CSemanticProgram::GetTaskClass() const
{
const CFunction* TaskFunction = GetTaskFunction();
if (!TaskFunction)
{
return nullptr;
}
const CTypeBase& ReturnType = TaskFunction->_Signature.GetFunctionType()->GetReturnType();
const CTypeType& ReturnTypeType = ReturnType.GetNormalType().AsChecked<CTypeType>();
return &ReturnTypeType.PositiveType()->GetNormalType().AsChecked<CClass>();
}
const CTypeBase* CSemanticProgram::InstantiateTaskType(const CTypeBase* TypeArgument)
{
const CFunction* TaskFunction = GetTaskFunction();
if (!TaskFunction)
{
return nullptr;
}
const CFunctionType* InstTaskType = SemanticTypeUtils::Instantiate(TaskFunction->_Signature.GetFunctionType());
// `task` does not make use of the negative part of the type argument. Any
// type at or above `TypeArgument` will do.
bool bConstrained = SemanticTypeUtils::Constrain(&GetOrCreateTypeType(&_anyType, TypeArgument), &InstTaskType->GetParamsType());
ULANG_ASSERTF(bConstrained, "Expected %s <= t for task(t)", TypeArgument->AsCode(ETypeSyntaxPrecedence::Comparison).AsCString());
const CTypeType& ParamTypeType = InstTaskType->GetParamsType().GetNormalType().AsChecked<CTypeType>();
const CFlowType* ParamNegativeFlowType = ParamTypeType.NegativeType()->AsFlowType();
ULANG_ASSERTF(ParamNegativeFlowType, "Failed to cast Type.");
// The negative part of the parameter type is now dead. Prune flow edges
// to improve instantiation cache.
ParamNegativeFlowType->EmptyFlowEdges();
const CTypeType& ReturnTypeType = InstTaskType->GetReturnType().GetNormalType().AsChecked<CTypeType>();
return ReturnTypeType.PositiveType();
}
CSnippet& CSemanticProgram::GetOrCreateSnippet(const CSymbol& Path, CScope* ParentScope)
{
// First, try to find the snippet
CSnippet* Snippet = _Snippets.Find(Path);
if (Snippet)
{
return *Snippet;
}
// Create it if not found
TURef<CSnippet> NewSnippet = TURef<CSnippet>::New(Path, ParentScope, *this);
Snippet = NewSnippet.Get();
_Snippets.Add(Move(NewSnippet));
return *Snippet;
}
CSnippet* CSemanticProgram::FindSnippet(const CUTF8StringView& NameStr) const
{
CSnippet* FoundSnippet = nullptr;
TOptional<CSymbol> MaybeSymbol = _Symbols->Find(NameStr);
if (MaybeSymbol)
{
FoundSnippet = _Snippets.Find(*MaybeSymbol);
}
return FoundSnippet;
}
CArrayType& CSemanticProgram::GetOrCreateArrayType(const CTypeBase* ElementType)
{
ULANG_ASSERTF(ElementType, "Unexpected null element type for array type");
CArrayType* ArrayType = _ArrayTypes.Find(ElementType);
if (!ArrayType)
{
TURef<CArrayType> NewArrayType = TURef<CArrayType>::New(*this, ElementType);
ArrayType = NewArrayType;
_ArrayTypes.Add(Move(NewArrayType));
}
return *ArrayType;
}
CGeneratorType& CSemanticProgram::GetOrCreateGeneratorType(const CTypeBase* ElementType)
{
ULANG_ASSERTF(ElementType, "Unexpected null element type for generator type");
CGeneratorType* GeneratorType = _GeneratorTypes.Find(ElementType);
if (!GeneratorType)
{
TURef<CGeneratorType> NewGeneratorType = TURef<CGeneratorType>::New(*this, ElementType);
GeneratorType = NewGeneratorType;
_GeneratorTypes.Add(Move(NewGeneratorType));
}
return *GeneratorType;
}
CMapType& CSemanticProgram::GetOrCreateMapType(const CTypeBase* KeyType, const CTypeBase* ValueType)
{
ULANG_ASSERTF(KeyType, "Unexpected null element type for map key type");
ULANG_ASSERTF(ValueType, "Unexpected null element type for map value type");
return GetOrCreateMapType(*KeyType, *ValueType, false);
}
CMapType& CSemanticProgram::GetOrCreateWeakMapType(const CTypeBase& KeyType, const CTypeBase& ValueType)
{
return GetOrCreateMapType(KeyType, ValueType, true);
}
CMapType& CSemanticProgram::GetOrCreateMapType(const CTypeBase& KeyType, const CTypeBase& ValueType, bool bWeak)
{
CMapType* MapType = _MapTypes.Find(CMapType::SKey{&KeyType, &ValueType, bWeak});
if (!MapType)
{
TURef<CMapType> NewMapType = TURef<CMapType>::New(*this, KeyType, ValueType, bWeak);
MapType = NewMapType;
_MapTypes.Add(Move(NewMapType));
}
return *MapType;
}
CPointerType& CSemanticProgram::GetOrCreatePointerType(const CTypeBase* NegativeValueType, const CTypeBase* PositiveValueType)
{
ULANG_ASSERTF(NegativeValueType, "Unexpected null value type for variable type");
ULANG_ASSERTF(PositiveValueType, "Unexpected null value type for variable type");
CPointerType* PointerType = _PointerTypes.Find({NegativeValueType, PositiveValueType});
if (!PointerType)
{
TURef<CPointerType> NewPointerType = TURef<CPointerType>::New(*this, NegativeValueType, PositiveValueType);
PointerType = NewPointerType;
_PointerTypes.Add(Move(NewPointerType));
}
return *PointerType;
}
CReferenceType& CSemanticProgram::GetOrCreateReferenceType(const CTypeBase* NegativeValueType, const CTypeBase* PositiveValueType)
{
ULANG_ASSERTF(NegativeValueType, "Unexpected null value type for variable type");
ULANG_ASSERTF(PositiveValueType, "Unexpected null value type for variable type");
CReferenceType* ReferenceType = _ReferenceTypes.Find({NegativeValueType, PositiveValueType});
if (!ReferenceType)
{
TURef<CReferenceType> NewReferenceType = TURef<CReferenceType>::New(*this, NegativeValueType, PositiveValueType);
ReferenceType = NewReferenceType;
_ReferenceTypes.Add(Move(NewReferenceType));
}
return *ReferenceType;
}
COptionType& CSemanticProgram::GetOrCreateOptionType(const CTypeBase* ValueType)
{
ULANG_ASSERTF(ValueType, "Unexpected null value type for option type");
COptionType* OptionType = _OptTypes.Find(ValueType);
if (!OptionType)
{
TURef<COptionType> NewOptionType = TURef<COptionType>::New(*this, ValueType);
OptionType = NewOptionType;
_OptTypes.Add(Move(NewOptionType));
}
return *OptionType;
}
CTypeType& CSemanticProgram::GetOrCreateTypeType(const CTypeBase* NegativeType, const CTypeBase* PositiveType)
{
ULANG_ASSERTF(NegativeType, "Unexpected null value type for negative type");
ULANG_ASSERTF(PositiveType, "Unexpected null value type for negative type");
CTypeType* TypeType = _TypeTypes.Find({NegativeType, PositiveType});
if (!TypeType)
{
TURef<CTypeType> NewTypeType = TURef<CTypeType>::New(*this, NegativeType, PositiveType);
TypeType = NewTypeType;
_TypeTypes.Add(Move(NewTypeType));
}
return *TypeType;
}
CTypeType& CSemanticProgram::GetOrCreateSubtypeType(const CTypeBase* NegativeType)
{
return GetOrCreateTypeType(&_falseType, NegativeType);
}
CCastableType& CSemanticProgram::GetOrCreateCastableType(const CTypeBase& SuperType)
{
ULANG_ASSERT(!SuperType.AsFlowType());
ULANG_ASSERT(!SuperType.GetNormalType().IsA<CCastableType>());
CCastableType* CastableType = _CastableTypes.Find({&SuperType});
if (!CastableType)
{
TURef<CCastableType> NewCastableType = TURef<CCastableType>::New(*this, SuperType);
CastableType = NewCastableType;
_CastableTypes.Add(Move(NewCastableType));
}
return *CastableType;
}
CTupleType& CSemanticProgram::GetOrCreateTupleType(CTupleType::ElementArray&& Elements)
{
return GetOrCreateTupleType(Move(Elements), Elements.Num());
}
CTupleType& CSemanticProgram::GetOrCreateTupleType(CTupleType::ElementArray&& Elements, int32_t FirstNamedIndex)
{
ULANG_ASSERT(FirstNamedIndex >= 0 && FirstNamedIndex <= Elements.Num());
if (!Elements.Num())
{
return _EmptyTupleType;
}
const CTypeBase* FirstElementType = Elements[0];
CTupleType* PreexistingTupleType = FirstElementType->_TupleTypesStartingWithThisType.FindByPredicate([&Elements, FirstNamedIndex](const CTupleType* TupleType)->bool
{
return TupleType->GetElements() == Elements && TupleType->GetFirstNamedIndex() == FirstNamedIndex;
});
if (PreexistingTupleType)
{
return *PreexistingTupleType;
}
for (const CTypeBase* Element : Elements)
{
ULANG_ASSERTF(Element, "Unexpected null element type for tuple type");
}
const int32_t TypeIndex = FirstElementType->_TupleTypesStartingWithThisType.AddNew(*this, Move(Elements), FirstNamedIndex);
return *FirstElementType->_TupleTypesStartingWithThisType[TypeIndex];
}
CNamedType& CSemanticProgram::GetOrCreateNamedType(CSymbol Name, const CTypeBase* ValueType, bool HasValue)
{
CNamedType* Result = _NamedTypes.Find({Name, ValueType, HasValue});
if (!Result)
{
TURef<CNamedType> NamedType = TURef<CNamedType>::New(
*this,
Name,
ValueType,
HasValue);
Result = NamedType.Get();
_NamedTypes.Add(Move(NamedType));
}
return *Result;
}
const CFunctionType& CSemanticProgram::GetOrCreateFunctionType(
const CTypeBase& ParamsType,
const CTypeBase& InReturnType,
SEffectSet Effects,
TArray<const CTypeVariable*> TypeVariables,
bool bImplicitlySpecialized)
{
const CFunctionType* PreexistingFuncType = ParamsType._FunctionTypesWithThisParameterType.FindByPredicate([&](const CFunctionType* FuncType)
{
return
FuncType->GetEffects() == Effects &&
&FuncType->GetParamsType() == &ParamsType &&
&FuncType->GetReturnType() == &InReturnType &&
FuncType->GetTypeVariables() == TypeVariables &&
FuncType->ImplicitlySpecialized() == bImplicitlySpecialized;
});
if (PreexistingFuncType)
{
return *PreexistingFuncType;
}
const int32_t TypeIndex = ParamsType._FunctionTypesWithThisParameterType.AddNew(*this, ParamsType, InReturnType, Effects, Move(TypeVariables), bImplicitlySpecialized);
return *ParamsType._FunctionTypesWithThisParameterType[TypeIndex];
}
const CIntType& CSemanticProgram::GetOrCreateConstrainedIntType(FIntOrNegativeInfinity Min, FIntOrPositiveInfinity Max)
{
const CIntType* PreexistingConstrainedInt = _ConstrainedIntTypes.FindByPredicate([&](const CIntType* ConstrainedInt)
{
return Min == ConstrainedInt->GetMin() && Max == ConstrainedInt->GetMax();
});
if (PreexistingConstrainedInt) { return *PreexistingConstrainedInt; }
const int32_t TypeIndex = _ConstrainedIntTypes.AddNew(*this, Min, Max);
return *_ConstrainedIntTypes[TypeIndex];
}
const CFloatType& CSemanticProgram::GetOrCreateConstrainedFloatType(double Min, double Max)
{
int64_t MinRanking = CMath::FloatRanking(Min);
int64_t MaxRanking = CMath::FloatRanking(Max);
const CFloatType* PreexistingType = _ConstrainedFloatTypes.FindByPredicate([&](const CFloatType* ConstrainedFloat)
{
return MinRanking == ConstrainedFloat->MinRanking() && MaxRanking == ConstrainedFloat->MaxRanking();
});
if (PreexistingType) { return *PreexistingType; }
const int32_t TypeIndex = _ConstrainedFloatTypes.AddNew(*this, Min, Max, MinRanking, MaxRanking);
return *_ConstrainedFloatTypes[TypeIndex];
}
CFlowType& CSemanticProgram::CreateFlowType(ETypePolarity Polarity)
{
switch (Polarity)
{
case ETypePolarity::Positive:
return CreatePositiveFlowType();
case ETypePolarity::Negative:
return CreateNegativeFlowType();
default:
ULANG_UNREACHABLE();
}
}
CFlowType& CSemanticProgram::CreateFlowType(ETypePolarity Polarity, const CTypeBase* Child)
{
int32_t I = _FlowTypes.AddNew(*this, Polarity, Child);
return *_FlowTypes[I];
}
CInstantiatedClass& CSemanticProgram::CreateInstantiatedClass(const CClass& Class, ETypePolarity Polarity, TArray<STypeVariableSubstitution> Arguments)
{
int32_t I = _InstantiatedClasses.AddNew(*this, Class, Polarity, Move(Arguments));
return *_InstantiatedClasses[I];
}
CInstantiatedInterface& CSemanticProgram::CreateInstantiatedInterface(const CInterface& Interface, ETypePolarity Polarity, TArray<STypeVariableSubstitution> Arguments)
{
int32_t I = _InstantiatedInterfaces.AddNew(*this, Interface, Polarity, Move(Arguments));
return *_InstantiatedInterfaces[I];
}
CSemanticProgram::SExplicitTypeParam CSemanticProgram::CreateExplicitTypeParam(
CFunction* Function,
CSymbol DataName,
CSymbol TypeName,
CSymbol NegativeTypeName,
const CTypeType* Type)
{
// See `SemanticTypeUtils::Instantiate` and `CSemanticAnalyzerImpl::AnalyzeParam`
// for details of the encoding of explicit type parameters as implicit type
// parameters.
TSRef<CTypeVariable> TypeVariable = Function->CreateTypeVariable(
TypeName,
Type,
Type);
CTypeType& NegativeTypeVariableType = GetOrCreateTypeType(&_falseType, TypeVariable.Get());
TSRef<CTypeVariable> NegativeTypeVariable = Function->CreateTypeVariable(
NegativeTypeName,
&NegativeTypeVariableType,
&NegativeTypeVariableType);
CTypeType& DataDefinitionType = GetOrCreateTypeType(
NegativeTypeVariable.Get(),
NegativeTypeVariable.Get());
TSRef<CDataDefinition> DataDefinition = Function->CreateDataDefinition(
DataName,
&DataDefinitionType);
DataDefinition->_NegativeType = &DataDefinitionType;
DataDefinition->_ImplicitParam = TypeVariable.Get();
TypeVariable->_ExplicitParam = DataDefinition.Get();
TypeVariable->_NegativeTypeVariable = NegativeTypeVariable;
NegativeTypeVariable->_ExplicitParam = DataDefinition.Get();
return {DataDefinition.Get(), TypeVariable.Get(), NegativeTypeVariable.Get()};
}
void CSemanticProgram::AddStandardAccessLevelAttributes(CAttributable* NewAccessLevel) const
{
NewAccessLevel->AddAttributeClass(_attributeScopeModule);
NewAccessLevel->AddAttributeClass(_attributeScopeClass);
NewAccessLevel->AddAttributeClass(_attributeScopeStruct);
NewAccessLevel->AddAttributeClass(_attributeScopeFunction);
NewAccessLevel->AddAttributeClass(_attributeScopeData);
NewAccessLevel->AddAttributeClass(_attributeScopeEnum);
NewAccessLevel->AddAttributeClass(_attributeScopeEnumerator);
NewAccessLevel->AddAttributeClass(_attributeScopeAttributeClass);
NewAccessLevel->AddAttributeClass(_attributeScopeInterface);
NewAccessLevel->AddAttributeClass(_attributeScopeName);
NewAccessLevel->AddAttributeClass(_attributeScopeTypeDefinition);
NewAccessLevel->AddAttributeClass(_attributeScopeClassMacro);
NewAccessLevel->AddAttributeClass(_attributeScopeStructMacro);
NewAccessLevel->AddAttributeClass(_attributeScopeInterfaceMacro);
NewAccessLevel->AddAttributeClass(_attributeScopeEnumMacro);
NewAccessLevel->AddAttributeClass(_attributeScopeVar);
NewAccessLevel->AddAttributeClass(_attributeScopeSpecifier);
NewAccessLevel->AddAttributeClass(_attributeScopeScopedDefinition);
}
void CSemanticProgram::PopulateCoreAPI()
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Ensure set up.
if (!_Symbols)
{
Initialize();
}
if (_VerseModule)
{
return;
}
_GeneralCompatConstraintRoot = TSRef<CCompatConstraintRoot>::New(*this);
_PersistenceCompatConstraintRoot = TSRef<CCompatConstraintRoot>::New(*this);
_PersistenceSoftCompatConstraintRoot = TSRef<CCompatConstraintRoot>::New(*this);
_BuiltInPackage = TSRef<CAstPackage>::New(
"$BuiltIn",
"/Verse.org",
EVerseScope::PublicAPI,
EPackageRole::External,
Verse::Version::LatestStable,
VerseFN::UploadedAtFNVersion::Latest,
false, // bAllowNative
false, // bTreatDefinitionsAsImplicit
true // bAllowExperimental
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Create and cache built-in types
auto MakeBuiltInModule = [&](const char* Name, CModulePart* ParentScope) -> CModulePart&
{
CScope* ModuleParentScope = ParentScope ? static_cast<CScope*>(ParentScope->GetModule()) : this;
CModule& Module = ModuleParentScope->CreateModule(GetSymbols()->AddChecked(Name));
Module.SetAccessLevel({ SAccessLevel::EKind::Public });
CModulePart& ModulePart = Module.CreatePart(ParentScope, true);
ModulePart.SetAstPackage(_BuiltInPackage.Get());
return ModulePart;
};
CModulePart& VerseDotOrgModuleBuiltInPart = MakeBuiltInModule("Verse.org", nullptr);
CModulePart& VerseModuleBuiltInPart = MakeBuiltInModule("Verse", &VerseDotOrgModuleBuiltInPart);
CModulePart& NativeModuleBuiltInPart = MakeBuiltInModule("Native", &VerseDotOrgModuleBuiltInPart);
_BuiltInPackage->_RootModule = &VerseDotOrgModuleBuiltInPart;
_VerseModule = VerseModuleBuiltInPart.GetModule();
AddUsingScope(_VerseModule);
_GeneralCompatConstraintRoot->AddUsingScope(_VerseModule);
_PersistenceCompatConstraintRoot->AddUsingScope(_VerseModule);
_PersistenceSoftCompatConstraintRoot->AddUsingScope(_VerseModule);
_typeType = &GetOrCreateTypeType(&_falseType, &_anyType);
_intType = &GetOrCreateConstrainedIntType(FIntOrNegativeInfinity::Infinity(), FIntOrPositiveInfinity::Infinity());
_floatType = &GetOrCreateConstrainedFloatType(-INFINITY, NAN);
// Create type aliases for the global types that are accessible by users.
auto CreateGlobalTypeAlias = [&](const CTypeBase* Type, const char* NameOverride = nullptr) -> CTypeAlias*
{
CSymbol Name = _Symbols->AddChecked(NameOverride ? NameOverride : Type->AsCode());
CTypeAlias* TypeAlias = VerseModuleBuiltInPart.CreateTypeAlias(Name);
TypeAlias->InitType(Type, Type);
TypeAlias->SetAccessLevel({SAccessLevel::EKind::Public});
return TypeAlias;
};
_falseAlias = CreateGlobalTypeAlias(&_falseType);
_trueAlias = CreateGlobalTypeAlias(&_trueType);
_voidAlias = CreateGlobalTypeAlias(&_voidType);
_anyAlias = CreateGlobalTypeAlias(&_anyType);
_comparableAlias = CreateGlobalTypeAlias(&_comparableType);
_logicAlias = CreateGlobalTypeAlias(&_logicType);
_intAlias = CreateGlobalTypeAlias(_intType);
_floatAlias = CreateGlobalTypeAlias(_floatType);
_rationalAlias = CreateGlobalTypeAlias(&_rationalType);
_char8Alias = CreateGlobalTypeAlias(&_char8Type);
_char32Alias = CreateGlobalTypeAlias(&_char32Type);
_stringAlias = CreateGlobalTypeAlias(&GetOrCreateArrayType(&_char8Type), "string");
_typeAlias = CreateGlobalTypeAlias(_typeType);
_DefaultUnknownType.SetNew(_Symbols->AddChecked("unknown"), VerseModuleBuiltInPart);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Populate attributes
// TODO-Verse: Consider - C# attributes have `Attribute` suffix though allow just the root. So `nativeAttribute` class would allow `[native]`.
// Could use prefix which would ensure starting with capital: `Attr_native`
auto CreateAttributeClass = [&](CModulePart& ParentScope, const char* Name, CClass* SuperClass = nullptr, SAccessLevel AccessLevel = SAccessLevel::EKind::Public) -> CClassDefinition*
{
CClassDefinition* Class = &ParentScope.CreateClass(_Symbols->AddChecked(Name), SuperClass);
Class->_ConstructorEffects = EffectSets::Computes;
Class->_bHasCyclesBroken = true;
Class->SetAccessLevel(AccessLevel);
return Class;
};
_attributeClass = CreateAttributeClass(VerseModuleBuiltInPart, "attribute", nullptr, SAccessLevel::EKind::EpicInternal);
{
_attributeScopeAttribute = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_attribute", _attributeClass, SAccessLevel::EKind::EpicInternal);
_attributeScopeSpecifier = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_specifier", _attributeClass, SAccessLevel::EKind::EpicInternal);
_attributeScopeModule = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_module", _attributeClass, SAccessLevel::EKind::EpicInternal);
_attributeScopeClass = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_class", _attributeClass, SAccessLevel::EKind::EpicInternal);
_attributeScopeStruct = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_struct", _attributeClass, SAccessLevel::EKind::EpicInternal);
_attributeScopeData = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_data", _attributeClass, SAccessLevel::EKind::EpicInternal);
_attributeScopeFunction = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_function", _attributeClass, SAccessLevel::EKind::EpicInternal);
_attributeScopeEnum = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_enum", _attributeClass, SAccessLevel::EKind::EpicInternal);
_attributeScopeEnumerator = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_enumerator", _attributeClass, SAccessLevel::EKind::EpicInternal);
_attributeScopeAttributeClass = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_attribclass", _attributeClass, SAccessLevel::EKind::EpicInternal);
_attributeScopeInterface = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_interface", _attributeClass, SAccessLevel::EKind::EpicInternal);
_attributeScopeIdentifier = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_identifier", _attributeClass, SAccessLevel::EKind::EpicInternal);
_attributeScopeExpression = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_expression", _attributeClass, SAccessLevel::EKind::EpicInternal);
_attributeScopeClassMacro = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_classmacro", _attributeClass, SAccessLevel::EKind::EpicInternal);
_attributeScopeStructMacro = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_structmacro", _attributeClass, SAccessLevel::EKind::EpicInternal);
_attributeScopeInterfaceMacro = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_interfacemacro", _attributeClass, SAccessLevel::EKind::EpicInternal);
_attributeScopeEnumMacro = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_enummacro", _attributeClass, SAccessLevel::EKind::EpicInternal);
_attributeScopeVar = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_var", _attributeClass, SAccessLevel::EKind::EpicInternal);
_attributeScopeName = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_name", _attributeClass, SAccessLevel::EKind::EpicInternal);
_attributeScopeEffect = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_effect", _attributeClass, SAccessLevel::EKind::EpicInternal);
_attributeScopeTypeDefinition = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_typedefinition", _attributeClass, SAccessLevel::EKind::EpicInternal);
_attributeScopeScopedDefinition = CreateAttributeClass(VerseModuleBuiltInPart, "attribscope_scopeddefinition", _attributeClass, SAccessLevel::EKind::EpicInternal);
_customAttributeHandler = CreateAttributeClass(VerseModuleBuiltInPart, "customattribhandler", _attributeClass, SAccessLevel::EKind::EpicInternal);
auto AddAttribScopeAttributes = [&](CClass* Class) -> void
{
Class->_Definition->AddAttributeClass(_attributeScopeAttributeClass);
Class->_Definition->AddAttributeClass(_attributeScopeAttribute);
};
AddAttribScopeAttributes(_attributeScopeAttribute);
AddAttribScopeAttributes(_attributeScopeSpecifier);
AddAttribScopeAttributes(_attributeScopeModule);
AddAttribScopeAttributes(_attributeScopeClass);
AddAttribScopeAttributes(_attributeScopeStruct);
AddAttribScopeAttributes(_attributeScopeData);
AddAttribScopeAttributes(_attributeScopeFunction);
AddAttribScopeAttributes(_attributeScopeEnum);
AddAttribScopeAttributes(_attributeScopeEnumerator);
AddAttribScopeAttributes(_attributeScopeAttributeClass);
AddAttribScopeAttributes(_attributeScopeInterface);
AddAttribScopeAttributes(_attributeScopeIdentifier);
AddAttribScopeAttributes(_attributeScopeExpression);
AddAttribScopeAttributes(_attributeScopeClassMacro);
AddAttribScopeAttributes(_attributeScopeStructMacro);
AddAttribScopeAttributes(_attributeScopeInterfaceMacro);
AddAttribScopeAttributes(_attributeScopeEnumMacro);
AddAttribScopeAttributes(_attributeScopeName);
AddAttribScopeAttributes(_attributeScopeEffect);
AddAttribScopeAttributes(_attributeScopeTypeDefinition);
AddAttribScopeAttributes(_attributeScopeScopedDefinition);
AddAttribScopeAttributes(_customAttributeHandler);
}
_abstractClass = CreateAttributeClass(VerseModuleBuiltInPart, "abstract", _attributeClass);
{
_abstractClass->_Definition->AddAttributeClass(_attributeScopeClassMacro);
_abstractClass->_Definition->AddAttributeClass(_attributeScopeClass);
_abstractClass->_Definition->AddAttributeClass(_attributeScopeSpecifier);
}
_finalClass = CreateAttributeClass(VerseModuleBuiltInPart, "final", _attributeClass);
{
// It's a bit of a hack that the classmacro scope needs to be used together with the name scope. This is to deal with the
// fact that final is otherwise used with names.
_finalClass->_Definition->AddAttributeClass(_attributeScopeFunction);
_finalClass->_Definition->AddAttributeClass(_attributeScopeData);
_finalClass->_Definition->AddAttributeClass(_attributeScopeClass);
_finalClass->_Definition->AddAttributeClass(_attributeScopeClassMacro);
_finalClass->_Definition->AddAttributeClass(_attributeScopeName);
_finalClass->_Definition->AddAttributeClass(_attributeScopeSpecifier);
}
_concreteClass = CreateAttributeClass(VerseModuleBuiltInPart, "concrete", _attributeClass);
{
_concreteClass->_Definition->AddAttributeClass(_attributeScopeClass);
_concreteClass->_Definition->AddAttributeClass(_attributeScopeClassMacro);
_concreteClass->_Definition->AddAttributeClass(_attributeScopeStruct);
_concreteClass->_Definition->AddAttributeClass(_attributeScopeStructMacro);
_concreteClass->_Definition->AddAttributeClass(_attributeScopeSpecifier);
}
_uniqueClass = CreateAttributeClass(VerseModuleBuiltInPart, "unique", _attributeClass);
{
_uniqueClass->_Definition->AddAttributeClass(_attributeScopeClass);
_uniqueClass->_Definition->AddAttributeClass(_attributeScopeClassMacro);
_uniqueClass->_Definition->AddAttributeClass(_attributeScopeInterface);
_uniqueClass->_Definition->AddAttributeClass(_attributeScopeInterfaceMacro);
_uniqueClass->_Definition->AddAttributeClass(_attributeScopeSpecifier);
}
_intrinsicClass = CreateAttributeClass(VerseModuleBuiltInPart, "intrinsic", _attributeClass, SAccessLevel::EKind::Private);
{
_intrinsicClass->_Definition->AddAttributeClass(_attributeScopeFunction);
_intrinsicClass->_Definition->AddAttributeClass(_attributeScopeSpecifier);
}
_nativeClass = CreateAttributeClass(VerseModuleBuiltInPart, "native", _attributeClass, SAccessLevel::EKind::EpicInternal);
{
_nativeClass->_Definition->AddAttributeClass(_attributeScopeClass);
_nativeClass->_Definition->AddAttributeClass(_attributeScopeStruct);
_nativeClass->_Definition->AddAttributeClass(_attributeScopeFunction);
_nativeClass->_Definition->AddAttributeClass(_attributeScopeData);
_nativeClass->_Definition->AddAttributeClass(_attributeScopeEnum);
_nativeClass->_Definition->AddAttributeClass(_attributeScopeEnumerator);
_nativeClass->_Definition->AddAttributeClass(_attributeScopeAttributeClass);
_nativeClass->_Definition->AddAttributeClass(_attributeScopeInterface);
_nativeClass->_Definition->AddAttributeClass(_attributeScopeName);
_nativeClass->_Definition->AddAttributeClass(_attributeScopeTypeDefinition);
_nativeClass->_Definition->AddAttributeClass(_attributeScopeSpecifier);
}
_nativeCallClass = CreateAttributeClass(VerseModuleBuiltInPart, "native_callable", _attributeClass, SAccessLevel::EKind::EpicInternal);
{
_nativeCallClass->_Definition->AddAttributeClass(_attributeScopeFunction);
_nativeCallClass->_Definition->AddAttributeClass(_attributeScopeName);
_nativeCallClass->_Definition->AddAttributeClass(_attributeScopeSpecifier);
}
_castableClass = CreateAttributeClass(VerseModuleBuiltInPart, "castable", _attributeClass);
{
_castableClass->_Definition->AddAttributeClass(_attributeScopeClass);
_castableClass->_Definition->AddAttributeClass(_attributeScopeClassMacro);
_castableClass->_Definition->AddAttributeClass(_attributeScopeInterface);
_castableClass->_Definition->AddAttributeClass(_attributeScopeInterfaceMacro);
}
_constructorClass = CreateAttributeClass(VerseModuleBuiltInPart, "constructor", _attributeClass);
{
_constructorClass->_Definition->AddAttributeClass(_attributeScopeFunction);
_constructorClass->_Definition->AddAttributeClass(_attributeScopeName);
_constructorClass->_Definition->AddAttributeClass(_attributeScopeIdentifier);
_constructorClass->_Definition->AddAttributeClass(_attributeScopeSpecifier);
}
_finalSuperBaseClass = CreateAttributeClass(VerseModuleBuiltInPart, "final_super_base", _attributeClass, SAccessLevel::EKind::EpicInternal);
{
// final_super_base only applies to class and interface declarations
_finalSuperBaseClass->_Definition->AddAttributeClass(_attributeScopeClass);
_finalSuperBaseClass->_Definition->AddAttributeClass(_attributeScopeClassMacro);
_finalSuperBaseClass->_Definition->AddAttributeClass(_attributeScopeInterface);
_finalSuperBaseClass->_Definition->AddAttributeClass(_attributeScopeInterfaceMacro);
}
_finalSuperClass = CreateAttributeClass(VerseModuleBuiltInPart, "final_super", _attributeClass);
{
// direct only applies to class declarations
_finalSuperClass->_Definition->AddAttributeClass(_attributeScopeClass);
_finalSuperClass->_Definition->AddAttributeClass(_attributeScopeClassMacro);
}
_overrideClass = CreateAttributeClass(VerseModuleBuiltInPart, "override", _attributeClass);
{
_overrideClass->_Definition->AddAttributeClass(_attributeScopeFunction);
_overrideClass->_Definition->AddAttributeClass(_attributeScopeData);
_overrideClass->_Definition->AddAttributeClass(_attributeScopeName);
_overrideClass->_Definition->AddAttributeClass(_attributeScopeSpecifier);
}
_openClass = CreateAttributeClass(VerseModuleBuiltInPart, "open", _attributeClass);
{
_openClass->_Definition->AddAttributeClass(_attributeScopeEnum);
_openClass->_Definition->AddAttributeClass(_attributeScopeEnumMacro);
}
_closedClass = CreateAttributeClass(VerseModuleBuiltInPart, "closed", _attributeClass);
{
_closedClass->_Definition->AddAttributeClass(_attributeScopeEnum);
_closedClass->_Definition->AddAttributeClass(_attributeScopeEnumMacro);
}
auto MakeEffectAttributeClass = [&](const char* Name, SAccessLevel AccessLevel = SAccessLevel::EKind::Public) -> CClassDefinition*
{
CClassDefinition* Result = CreateAttributeClass(VerseModuleBuiltInPart, Name, _attributeClass, AccessLevel);
Result->AddAttributeClass(_attributeScopeFunction);
Result->AddAttributeClass(_attributeScopeClass);
Result->AddAttributeClass(_attributeScopeStruct);
Result->AddAttributeClass(_attributeScopeAttributeClass);
Result->AddAttributeClass(_attributeScopeEffect);
Result->AddAttributeClass(_attributeScopeSpecifier);
return Result;
};
auto MakeAccessLevelAttributeClass = [&](const char* Name, SAccessLevel AccessLevel = SAccessLevel::EKind::Public) -> CClassDefinition*
{
CClassDefinition* Result = CreateAttributeClass(VerseModuleBuiltInPart, Name, _attributeClass, AccessLevel);
AddStandardAccessLevelAttributes(Result);
return Result;
};
_suspendsClass = MakeEffectAttributeClass("suspends");
_decidesClass = MakeEffectAttributeClass("decides");
_variesClassDeprecated = MakeEffectAttributeClass("varies");
_computesClass = MakeEffectAttributeClass("computes");
_convergesClass = MakeEffectAttributeClass("converges");
_transactsClass = MakeEffectAttributeClass("transacts");
_readsClass = MakeEffectAttributeClass("reads");
_writesClass = MakeEffectAttributeClass("writes");
_allocatesClass = MakeEffectAttributeClass("allocates");
_predictsClass = MakeEffectAttributeClass("predicts", SAccessLevel::EKind::EpicInternal);
_publicClass = MakeAccessLevelAttributeClass("public");
_privateClass = MakeAccessLevelAttributeClass("private");
_protectedClass = MakeAccessLevelAttributeClass("protected");
_internalClass = MakeAccessLevelAttributeClass("internal");
_scopedClass = MakeAccessLevelAttributeClass("scoped");
_epicInternalClass = MakeAccessLevelAttributeClass("epic_internal", SAccessLevel::EKind::EpicInternal);
PopulateEffectDescriptorTable();
_localizes = CreateAttributeClass(VerseModuleBuiltInPart, "localizes", _attributeClass, SAccessLevel::EKind::Public);
{
_localizes->_Definition->AddAttributeClass(_attributeScopeName);
_localizes->_Definition->AddAttributeClass(_attributeScopeData);
_localizes->_Definition->AddAttributeClass(_attributeScopeSpecifier);
_localizes->_Definition->AddAttributeClass(_attributeScopeFunction);
}
_ignore_unreachable = CreateAttributeClass(VerseModuleBuiltInPart, "ignore_unreachable", _attributeClass, SAccessLevel::EKind::EpicInternal);
{
_ignore_unreachable->_Definition->AddAttributeClass(_attributeScopeExpression);
_ignore_unreachable->_Definition->AddAttributeClass(_attributeScopeAttribute);
}
_availableClass = CreateAttributeClass(NativeModuleBuiltInPart, "available", _attributeClass, SAccessLevel::EKind::EpicInternal);
{
_availableClass->_Definition->AddAttributeClass(_attributeScopeClass);
_availableClass->_Definition->AddAttributeClass(_attributeScopeStruct);
_availableClass->_Definition->AddAttributeClass(_attributeScopeData);
_availableClass->_Definition->AddAttributeClass(_attributeScopeFunction);
_availableClass->_Definition->AddAttributeClass(_attributeScopeEnum);
_availableClass->_Definition->AddAttributeClass(_attributeScopeEnumerator);
_availableClass->_Definition->AddAttributeClass(_attributeScopeInterface);
_availableClass->_Definition->AddAttributeClass(_attributeScopeAttribute);
_availableClass->_Definition->AddAttributeClass(_attributeScopeTypeDefinition);
// TODO: Modules are unique in that multiple modules with the same name are coalesced (CModulePart),
// TODO: but the attributes are not combined in a meaningful way. We can't support that until the
// TODO: module-parts can retain their own @available versioning.
//_availableClass->_Definition->AddAttributeClass(_attributeScopeModule);
TSPtr<CDataDefinition> availableMinUploadedAtFNVersion = _availableClass->_Definition->CreateDataDefinition(_IntrinsicSymbols._MinUploadedAtFNVersion, _intType);
availableMinUploadedAtFNVersion->_NegativeType = _intType;
availableMinUploadedAtFNVersion->SetAccessLevel(SAccessLevel(SAccessLevel::EKind::Public));
availableMinUploadedAtFNVersion->SetHasInitializer();
}
_deprecatedClass = CreateAttributeClass(VerseModuleBuiltInPart, "deprecated", _attributeClass, SAccessLevel::EKind::EpicInternal);
{
_deprecatedClass->_Definition->AddAttributeClass(_attributeScopeClass);
_deprecatedClass->_Definition->AddAttributeClass(_attributeScopeStruct);
_deprecatedClass->_Definition->AddAttributeClass(_attributeScopeData);
_deprecatedClass->_Definition->AddAttributeClass(_attributeScopeFunction);
_deprecatedClass->_Definition->AddAttributeClass(_attributeScopeEnum);
_deprecatedClass->_Definition->AddAttributeClass(_attributeScopeEnumerator);
_deprecatedClass->_Definition->AddAttributeClass(_attributeScopeInterface);
_deprecatedClass->_Definition->AddAttributeClass(_attributeScopeAttribute);
_deprecatedClass->_Definition->AddAttributeClass(_attributeScopeTypeDefinition);
_deprecatedClass->_Definition->AddAttributeClass(_attributeScopeModule);
}
_experimentalClass = CreateAttributeClass(VerseModuleBuiltInPart, "experimental", _attributeClass, SAccessLevel::EKind::EpicInternal);
{
_experimentalClass->_Definition->AddAttributeClass(_attributeScopeClass);
_experimentalClass->_Definition->AddAttributeClass(_attributeScopeStruct);
_experimentalClass->_Definition->AddAttributeClass(_attributeScopeData);
_experimentalClass->_Definition->AddAttributeClass(_attributeScopeFunction);
_experimentalClass->_Definition->AddAttributeClass(_attributeScopeEnum);
_experimentalClass->_Definition->AddAttributeClass(_attributeScopeEnumerator);
_experimentalClass->_Definition->AddAttributeClass(_attributeScopeInterface);
_experimentalClass->_Definition->AddAttributeClass(_attributeScopeTypeDefinition);
_experimentalClass->_Definition->AddAttributeClass(_attributeScopeAttribute);
}
_persistentClass = CreateAttributeClass(VerseModuleBuiltInPart, "persistent", _attributeClass, SAccessLevel::EKind::EpicInternal);
{
_persistentClass->_Definition->AddAttributeClass(_attributeScopeClass);
_persistentClass->_Definition->AddAttributeClass(_attributeScopeClassMacro);
_persistentClass->_Definition->AddAttributeClass(_attributeScopeStruct);
_persistentClass->_Definition->AddAttributeClass(_attributeScopeStructMacro);
_persistentClass->_Definition->AddAttributeClass(_attributeScopeSpecifier);
}
_persistableClass = CreateAttributeClass(VerseModuleBuiltInPart, "persistable", _attributeClass, SAccessLevel::EKind::Public);
{
_persistableClass->_Definition->AddAttributeClass(_attributeScopeClass);
_persistableClass->_Definition->AddAttributeClass(_attributeScopeClassMacro);
_persistableClass->_Definition->AddAttributeClass(_attributeScopeStruct);
_persistableClass->_Definition->AddAttributeClass(_attributeScopeStructMacro);
_persistableClass->_Definition->AddAttributeClass(_attributeScopeEnum);
_persistableClass->_Definition->AddAttributeClass(_attributeScopeEnumMacro);
_persistableClass->_Definition->AddAttributeClass(_attributeScopeSpecifier);
}
_moduleScopedVarWeakMapKeyClass = CreateAttributeClass(VerseModuleBuiltInPart, "module_scoped_var_weak_map_key", _attributeClass, SAccessLevel::EKind::EpicInternal);
{
_moduleScopedVarWeakMapKeyClass->_Definition->AddAttributeClass(_attributeScopeClass);
_moduleScopedVarWeakMapKeyClass->_Definition->AddAttributeClass(_attributeScopeClassMacro);
_moduleScopedVarWeakMapKeyClass->_Definition->AddAttributeClass(_attributeScopeSpecifier);
}
_rtfmAlwaysOpen = CreateAttributeClass(VerseModuleBuiltInPart, "rtfm_always_open", _attributeClass, SAccessLevel::EKind::EpicInternal);
{
_rtfmAlwaysOpen->_Definition->AddAttributeClass(_attributeScopeFunction);
}
_getterClass = CreateAttributeClass(VerseModuleBuiltInPart, "getter_attribute", _attributeClass, SAccessLevel::EKind::EpicInternal);
{
_getterClass->_Definition->AddAttributeClass(_attributeScopeData);
_getterClass->_Definition->AddAttributeClass(_attributeScopeName);
_getterClass->_Definition->AddAttributeClass(_attributeScopeSpecifier);
}
_setterClass = CreateAttributeClass(VerseModuleBuiltInPart, "setter_attribute", _attributeClass, SAccessLevel::EKind::EpicInternal);
{
_setterClass->_Definition->AddAttributeClass(_attributeScopeData);
_setterClass->_Definition->AddAttributeClass(_attributeScopeName);
_setterClass->_Definition->AddAttributeClass(_attributeScopeSpecifier);
}
{
_predictsClass->_Definition->AddAttributeClass(_attributeScopeData);
_predictsClass->_Definition->AddAttributeClass(_attributeScopeName);
_predictsClass->_Definition->AddAttributeClass(_attributeScopeSpecifier);
}
// TODO-Verse: Likely future attributes:
// - [deprecated] - gives warning when used
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Populate intrinsic operators
const CSymbol ValName = _Symbols->AddChecked("Value");
const CSymbol LhsName = _Symbols->AddChecked("Lhs");
const CSymbol RhsName = _Symbols->AddChecked("Rhs");
struct STypedName
{
CSymbol Name;
const CTypeBase* Type;
};
auto CreateFunction = [this, &VerseModuleBuiltInPart](CSymbol FunctionName, std::initializer_list<STypedName> Params, auto&&... Args) -> CFunction*
{
TSRef<CFunction> NewFunction = VerseModuleBuiltInPart.CreateFunction(FunctionName);
const CTypeBase* ParamsType;
std::size_t NumParams = Params.size();
if (NumParams == 1)
{
ParamsType = Params.begin()->Type;
}
else
{
CTupleType::ElementArray ParamTypes;
ParamTypes.Reserve(static_cast<int32_t>(NumParams));
for (const STypedName& Param : Params)
{
ParamTypes.Add(Param.Type);
}
ParamsType = &GetOrCreateTupleType(Move(ParamTypes));
}
const CFunctionType& FunctionType = GetOrCreateFunctionType(
*ParamsType,
uLang::ForwardArg<decltype(Args)>(Args)...);
TArray<CDataDefinition*> ParamDataDefinitions;
ParamDataDefinitions.Reserve(static_cast<int32_t>(NumParams));
for (const STypedName& Param : Params)
{
TSRef<CDataDefinition> ParamDataDefinition = NewFunction->CreateDataDefinition(Param.Name);
ParamDataDefinition->SetType(Param.Type);
ParamDataDefinitions.Add(ParamDataDefinition.Get());
}
NewFunction->_NegativeType = &FunctionType;
NewFunction->_Signature = SSignature(
FunctionType,
Move(ParamDataDefinitions));
NewFunction->SetAccessLevel({SAccessLevel::EKind::Public});
return NewFunction.Get();
};
auto&& CreateIntrinsicFunction = [this, &CreateFunction](CSymbol FunctionName, std::initializer_list<STypedName> Params, auto&&... Args) -> CFunction* {
CFunction* NewFunction = CreateFunction(FunctionName, Params, Args...);
NewFunction->AddAttributeClass(_intrinsicClass);
return NewFunction;
};
// Create all the effects sets we use in intrinsics here and assert if any of them are technically illegal (ie. couldn't be created from Verse code)
SEffectSet ConvergesEffectSet = ConvertEffectClassesToEffectSet({ _convergesClass }, EffectSets::FunctionDefault).GetValue();
SEffectSet ConvergesDecidesEffectSet = ConvertEffectClassesToEffectSet({ _convergesClass, _decidesClass }, EffectSets::FunctionDefault).GetValue();
SEffectSet ConvergesReadsDecidesEffectSet = ConvertEffectClassesToEffectSet({ _convergesClass, _readsClass, _decidesClass }, EffectSets::FunctionDefault).GetValue();
SEffectSet ComputesEffectSet = ConvertEffectClassesToEffectSet({ _computesClass }, EffectSets::FunctionDefault).GetValue();
SEffectSet TransactsEffectSet = ConvertEffectClassesToEffectSet({ _transactsClass }, EffectSets::FunctionDefault).GetValue();
SEffectSet TransactsDecidesEffectSet = ConvertEffectClassesToEffectSet({ _transactsClass, _decidesClass }, EffectSets::FunctionDefault).GetValue();
// `FunctionName`(`LhsName`:t, `RhsName`:comparable where t:subtype(comparable)):t
auto ComparableOp = [this, LhsName, RhsName, ConvergesDecidesEffectSet, &VerseModuleBuiltInPart](CSymbol FunctionName)
{
TSRef<CFunction> NewFunction = VerseModuleBuiltInPart.CreateFunction(FunctionName);
TSRef<CTypeVariable> Type = NewFunction->CreateTypeVariable(
_Symbols->AddChecked("t"),
&GetOrCreateTypeType(&_falseType, &_comparableType),
&GetOrCreateTypeType(&_falseType, &_comparableType));
const CFunctionType& FunctionType = GetOrCreateFunctionType(
GetOrCreateTupleType({Type.Get(), &_comparableType}),
*Type,
ConvergesDecidesEffectSet,
{Type.Get()});
NewFunction->_NegativeType = &FunctionType;
NewFunction->_Signature = SSignature(FunctionType, {
NewFunction->CreateDataDefinition(LhsName, Type.Get()),
NewFunction->CreateDataDefinition(RhsName, &_comparableType)});
NewFunction->SetAccessLevel({SAccessLevel::EKind::Public});
NewFunction->AddAttributeClass(_intrinsicClass);
return NewFunction.Get();
};
auto AddUnaryOp = [ValName, CreateIntrinsicFunction, ConvergesEffectSet, ConvergesDecidesEffectSet](const CTypeBase* OpType, const CSymbol& FunctionName, bool bFallible = false) -> CFunction*
{
return CreateIntrinsicFunction(
FunctionName,
/*Params =*/{{ValName, OpType}},
/*ReturnType =*/*OpType,
bFallible ? ConvergesDecidesEffectSet : ConvergesEffectSet);
};
auto AddBinaryOp = [LhsName, RhsName, CreateIntrinsicFunction, ConvergesEffectSet, ConvergesDecidesEffectSet](const CTypeBase* OpType, const CSymbol& FunctionName, bool bFallible = false) -> CFunction*
{
return CreateIntrinsicFunction(
FunctionName,
/*Params =*/{{LhsName, OpType}, {RhsName, OpType}},
/*ReturnType =*/*OpType,
bFallible ? ConvergesDecidesEffectSet : ConvergesEffectSet);
};
auto AddAsymmetricBinaryOp = [LhsName, RhsName, CreateIntrinsicFunction, ConvergesEffectSet, ConvergesDecidesEffectSet](const CTypeBase* LeftType, const CTypeBase* RightType, const CTypeBase* ResultType, const CSymbol& FunctionName, bool bFallible = false) -> CFunction*
{
return CreateIntrinsicFunction(
FunctionName,
/*Params =*/{{LhsName, LeftType}, {RhsName, RightType}},
/*ReturnType =*/*ResultType,
bFallible ? ConvergesDecidesEffectSet : ConvergesEffectSet);
};
auto AddAssignOp = [this, LhsName, RhsName, CreateIntrinsicFunction, TransactsDecidesEffectSet, TransactsEffectSet](const CTypeBase* OpType, const CSymbol& FunctionName, bool bFallible = false) -> CFunction*
{
const CTypeBase* ReferenceType = &GetOrCreateReferenceType(OpType, OpType);
return CreateIntrinsicFunction(
FunctionName,
/*Params =*/{{LhsName, ReferenceType}, {RhsName, OpType}},
/*ReturnType =*/*OpType,
bFallible ? TransactsDecidesEffectSet : TransactsEffectSet);
};
auto AddIntDivide = [this, LhsName, RhsName, CreateIntrinsicFunction, ConvergesDecidesEffectSet]() -> CFunction*
{
return CreateIntrinsicFunction(
_IntrinsicSymbols._OpNameDiv,
/*Params =*/{{LhsName, _intType}, {RhsName, _intType}},
/*ReturnType =*/_rationalType,
ConvergesDecidesEffectSet);
};
auto AddRationalOp = [this, ValName, CreateIntrinsicFunction, ConvergesEffectSet](CSymbol FunctionName)
{
return CreateIntrinsicFunction(
FunctionName,
/*Params =*/{{ValName, &_rationalType}},
/*ReturnType =*/*_intType,
ConvergesEffectSet);
};
_ComparableEqualOp = ComparableOp(_IntrinsicSymbols._OpNameEqual);
_ComparableNotEqualOp = ComparableOp(_IntrinsicSymbols._OpNameNotEqual);
_IntNegateOp = AddUnaryOp (_intType, _IntrinsicSymbols._OpNameNegate);
_IntAddOp = AddBinaryOp(_intType, _IntrinsicSymbols._OpNameAdd);
_IntSubtractOp = AddBinaryOp(_intType, _IntrinsicSymbols._OpNameSub);
_IntMultiplyOp = AddBinaryOp(_intType, _IntrinsicSymbols._OpNameMul);
_IntDivideOp = AddIntDivide();
_IntAddAssignOp = AddAssignOp(_intType, _IntrinsicSymbols._OpNameAddRMW);
_IntSubtractAssignOp = AddAssignOp(_intType, _IntrinsicSymbols._OpNameSubRMW);
_IntMultiplyAssignOp = AddAssignOp(_intType, _IntrinsicSymbols._OpNameMulRMW);
_IntAbs = AddUnaryOp (_intType, _IntrinsicSymbols._FuncNameAbs);
_IntGreaterOp = AddBinaryOp(_intType, _IntrinsicSymbols._OpNameGreater, true);
_IntGreaterEqualOp = AddBinaryOp(_intType, _IntrinsicSymbols._OpNameGreaterEqual, true);
_IntLessOp = AddBinaryOp(_intType, _IntrinsicSymbols._OpNameLess, true);
_IntLessEqualOp = AddBinaryOp(_intType, _IntrinsicSymbols._OpNameLessEqual, true);
_MakeRationalFromInt = CreateIntrinsicFunction(
_Symbols->AddChecked("MakeRationalFromInt"),
/*Params =*/{{ValName, _intType}},
/*ReturnType =*/_rationalType,
ConvergesEffectSet);
_MakeRationalFromInt->SetAccessLevel({SAccessLevel::EKind::EpicInternal});
_RationalCeil = AddRationalOp(_IntrinsicSymbols._FuncNameCeil);
_RationalFloor = AddRationalOp(_IntrinsicSymbols._FuncNameFloor);
_FloatNegateOp = AddUnaryOp (_floatType, _IntrinsicSymbols._OpNameNegate);
_FloatAddOp = AddBinaryOp(_floatType, _IntrinsicSymbols._OpNameAdd);
_FloatSubtractOp = AddBinaryOp(_floatType, _IntrinsicSymbols._OpNameSub);
_FloatMultiplyOp = AddBinaryOp(_floatType, _IntrinsicSymbols._OpNameMul);
_FloatDivideOp = AddBinaryOp(_floatType, _IntrinsicSymbols._OpNameDiv);
_FloatAddAssignOp = AddAssignOp(_floatType, _IntrinsicSymbols._OpNameAddRMW);
_FloatSubtractAssignOp = AddAssignOp(_floatType, _IntrinsicSymbols._OpNameSubRMW);
_FloatMultiplyAssignOp = AddAssignOp(_floatType, _IntrinsicSymbols._OpNameMulRMW);
_FloatDivideAssignOp = AddAssignOp(_floatType, _IntrinsicSymbols._OpNameDivRMW);
_FloatAbs = AddUnaryOp (_floatType, _IntrinsicSymbols._FuncNameAbs);
_IntMultiplyFloatOp = AddAsymmetricBinaryOp(_intType, _floatType, _floatType, _IntrinsicSymbols._OpNameMul);
_FloatMultiplyIntOp = AddAsymmetricBinaryOp(_floatType, _intType, _floatType, _IntrinsicSymbols._OpNameMul);
_FloatGreaterOp = AddBinaryOp(_floatType, _IntrinsicSymbols._OpNameGreater, true);
_FloatGreaterEqualOp = AddBinaryOp(_floatType, _IntrinsicSymbols._OpNameGreaterEqual, true);
_FloatLessOp = AddBinaryOp(_floatType, _IntrinsicSymbols._OpNameLess, true);
_FloatLessEqualOp = AddBinaryOp(_floatType, _IntrinsicSymbols._OpNameLessEqual, true);
_LogicQueryOp = AddUnaryOp(&_logicType, _IntrinsicSymbols._OpNameQuery, true);
//
// Array generics
//
{
_ArrayAddOp = VerseModuleBuiltInPart.CreateFunction(_IntrinsicSymbols._OpNameAdd);
TSRef<CTypeVariable> ElementType = _ArrayAddOp->CreateTypeVariable(
_Symbols->AddChecked("t"),
_typeType,
_typeType);
CArrayType& ArrayType = GetOrCreateArrayType(ElementType.Get());
const CFunctionType& FunctionType = GetOrCreateFunctionType(
GetOrCreateTupleType({&ArrayType, &ArrayType}),
ArrayType,
ConvergesEffectSet,
{ElementType.Get()},
true);
_ArrayAddOp->_NegativeType = &FunctionType;
_ArrayAddOp->_Signature = SSignature(FunctionType, {
_ArrayAddOp->CreateDataDefinition(LhsName, &ArrayType),
_ArrayAddOp->CreateDataDefinition(RhsName, &ArrayType)});
_ArrayAddOp->SetAccessLevel({SAccessLevel::EKind::Public});
_ArrayAddOp->AddAttributeClass(_intrinsicClass);
}
{
_ArrayAddAssignOp = VerseModuleBuiltInPart.CreateFunction(_IntrinsicSymbols._OpNameAddRMW);
TSRef<CTypeVariable> ElementType = _ArrayAddAssignOp->CreateTypeVariable(
_Symbols->AddChecked("t"),
_typeType,
_typeType);
CArrayType& ArrayType = GetOrCreateArrayType(ElementType.Get());
CReferenceType& ArrayReferenceType = GetOrCreateReferenceType(&ArrayType, &ArrayType);
const CFunctionType& FunctionType = GetOrCreateFunctionType(
GetOrCreateTupleType({&ArrayReferenceType, &ArrayType}),
ArrayType,
TransactsEffectSet,
{ElementType.Get()},
true);
_ArrayAddAssignOp->_NegativeType = &FunctionType;
_ArrayAddAssignOp->_Signature = SSignature(FunctionType, {
_ArrayAddAssignOp->CreateDataDefinition(LhsName, &ArrayReferenceType),
_ArrayAddAssignOp->CreateDataDefinition(RhsName, &ArrayType)});
_ArrayAddAssignOp->SetAccessLevel({SAccessLevel::EKind::Public});
_ArrayAddAssignOp->AddAttributeClass(_intrinsicClass);
}
{
_ArrayLength = CreateIntrinsicFunction(
_Symbols->AddChecked("operator'array.Length'"),
/*Params =*/{},
/*ReturnType =*/*_intType,
ConvergesEffectSet);
_ArrayLength->_ExtensionFieldAccessorKind = EExtensionFieldAccessorKind::ExtensionDataMember;
}
{
_ArrayCallOp = VerseModuleBuiltInPart.CreateFunction(_IntrinsicSymbols._OpNameCall);
TSRef<CTypeVariable> ElementType = _ArrayCallOp->CreateTypeVariable(
_Symbols->AddChecked("t"),
_typeType,
_typeType);
CArrayType& ArrayType = GetOrCreateArrayType(ElementType.Get());
const CFunctionType& FunctionType = GetOrCreateFunctionType(
GetOrCreateTupleType({&ArrayType, _intType}),
*ElementType,
ConvergesDecidesEffectSet,
{ElementType.Get()},
true);
_ArrayCallOp->_NegativeType = &FunctionType;
_ArrayCallOp->_Signature = SSignature(FunctionType, {
_ArrayCallOp->CreateDataDefinition(_Symbols->AddChecked("Array"), &ArrayType),
_ArrayCallOp->CreateDataDefinition(_Symbols->AddChecked("Index"), _intType)});
_ArrayCallOp->SetAccessLevel({SAccessLevel::EKind::Public});
_ArrayCallOp->AddAttributeClass(_intrinsicClass);
}
{
_ArrayRefCallOp = VerseModuleBuiltInPart.CreateFunction(_IntrinsicSymbols._OpNameCall);
TSRef<CTypeVariable> ElementType = _ArrayRefCallOp->CreateTypeVariable(
_Symbols->AddChecked("t"),
_typeType,
_typeType);
CArrayType& ArrayType = GetOrCreateArrayType(ElementType.Get());
CReferenceType& ArrayReferenceType = GetOrCreateReferenceType(&ArrayType, &ArrayType);
const CFunctionType& FunctionType = GetOrCreateFunctionType(
GetOrCreateTupleType({&ArrayReferenceType, _intType}),
GetOrCreateReferenceType(ElementType.Get(), ElementType.Get()),
TransactsDecidesEffectSet,
{ElementType.Get()},
true);
_ArrayRefCallOp->_NegativeType = &FunctionType;
_ArrayRefCallOp->_Signature = SSignature(FunctionType, {
_ArrayRefCallOp->CreateDataDefinition(_Symbols->AddChecked("Array"), &ArrayReferenceType),
_ArrayRefCallOp->CreateDataDefinition(_Symbols->AddChecked("Index"), _intType)});
_ArrayRefCallOp->SetAccessLevel({SAccessLevel::EKind::Public});
_ArrayRefCallOp->AddAttributeClass(_intrinsicClass);
}
CTypeType& ComparableSubtypeType = GetOrCreateTypeType(&_falseType, &_comparableType);
//
// Map generics
//
{
_MapRefCallOp = VerseModuleBuiltInPart.CreateFunction(_IntrinsicSymbols._OpNameCall);
TSRef<CTypeVariable> KeyType = _MapRefCallOp->CreateTypeVariable(
_Symbols->AddChecked("t"),
&ComparableSubtypeType,
&ComparableSubtypeType);
TSRef<CTypeVariable> ValueType = _MapRefCallOp->CreateTypeVariable(
_Symbols->AddChecked("u"),
_typeType,
_typeType);
CMapType& MapType = GetOrCreateMapType(KeyType.Get(), ValueType.Get());
CReferenceType& MapReferenceType = GetOrCreateReferenceType(&MapType, &MapType);
const CFunctionType& FunctionType = GetOrCreateFunctionType(
GetOrCreateTupleType({&MapReferenceType, KeyType.Get()}),
GetOrCreateReferenceType(ValueType.Get(), ValueType.Get()),
TransactsDecidesEffectSet,
{KeyType.Get(), ValueType.Get()},
true);
_MapRefCallOp->_NegativeType = &FunctionType;
_MapRefCallOp->_Signature = SSignature(FunctionType, {
_MapRefCallOp->CreateDataDefinition(_Symbols->AddChecked("Map"), &MapReferenceType),
_MapRefCallOp->CreateDataDefinition(_Symbols->AddChecked("Key"), KeyType.Get())
});
_MapRefCallOp->SetAccessLevel({SAccessLevel::EKind::Public});
_MapRefCallOp->AddAttributeClass(_intrinsicClass);
}
{
_MapLength = CreateIntrinsicFunction(
_Symbols->AddChecked("operator'map.Length'"),
/*Params =*/{},
/*ReturnType =*/*_intType,
ConvergesEffectSet);
_MapLength->_ExtensionFieldAccessorKind = EExtensionFieldAccessorKind::ExtensionDataMember;
}
{
_MapConcatenateMaps = VerseModuleBuiltInPart.CreateFunction(_Symbols->AddChecked("ConcatenateMaps"));
TSRef<CTypeVariable> KeyType = _MapConcatenateMaps->CreateTypeVariable(
_Symbols->AddChecked("t"),
&ComparableSubtypeType,
&ComparableSubtypeType);
TSRef<CTypeVariable> ValueType = _MapConcatenateMaps->CreateTypeVariable(
_Symbols->AddChecked("u"),
_typeType,
_typeType);
CMapType& MapType = GetOrCreateMapType(KeyType.Get(), ValueType.Get());
const CFunctionType& FunctionType = GetOrCreateFunctionType(
GetOrCreateTupleType({&MapType, &MapType}),
MapType,
ConvergesEffectSet,
{KeyType.Get(), ValueType.Get()},
true);
_MapConcatenateMaps->_NegativeType = &FunctionType;
_MapConcatenateMaps->_Signature = SSignature(FunctionType, {
_MapConcatenateMaps->CreateDataDefinition(LhsName, &MapType),
_MapConcatenateMaps->CreateDataDefinition(RhsName, &MapType)});
_MapConcatenateMaps->SetAccessLevel({SAccessLevel::EKind::Public});
_MapConcatenateMaps->AddAttributeClass(_intrinsicClass);
}
//
// Weak map generics
//
{
_WeakMapCallOp = VerseModuleBuiltInPart.CreateFunction(_IntrinsicSymbols._OpNameCall);
TSRef<CTypeVariable> KeyType = _WeakMapCallOp->CreateTypeVariable(
_Symbols->AddChecked("t"),
&ComparableSubtypeType,
&ComparableSubtypeType);
TSRef<CTypeVariable> ValueType = _WeakMapCallOp->CreateTypeVariable(
_Symbols->AddChecked("u"),
_typeType,
_typeType);
CMapType& MapType = GetOrCreateWeakMapType(*KeyType, *ValueType);
const CFunctionType& FunctionType = GetOrCreateFunctionType(
GetOrCreateTupleType({&MapType, KeyType.Get()}),
*ValueType,
ConvergesDecidesEffectSet,
{KeyType.Get(), ValueType.Get()},
true);
_WeakMapCallOp->_NegativeType = &FunctionType;
_WeakMapCallOp->_Signature = SSignature(FunctionType, {
_WeakMapCallOp->CreateDataDefinition(_Symbols->AddChecked("Map"), &MapType),
_WeakMapCallOp->CreateDataDefinition(_Symbols->AddChecked("Key"), KeyType.Get())});
_WeakMapCallOp->SetAccessLevel({SAccessLevel::EKind::Public});
_WeakMapCallOp->AddAttributeClass(_intrinsicClass);
}
{
_WeakMapRefCallOp = VerseModuleBuiltInPart.CreateFunction(_IntrinsicSymbols._OpNameCall);
TSRef<CTypeVariable> KeyType = _WeakMapRefCallOp->CreateTypeVariable(
_Symbols->AddChecked("t"),
&ComparableSubtypeType,
&ComparableSubtypeType);
TSRef<CTypeVariable> ValueType = _WeakMapRefCallOp->CreateTypeVariable(
_Symbols->AddChecked("u"),
_typeType,
_typeType);
CMapType& MapType = GetOrCreateWeakMapType(*KeyType, *ValueType);
CReferenceType& MapReferenceType = GetOrCreateReferenceType(&MapType, &MapType);
const CFunctionType& FunctionType = GetOrCreateFunctionType(
GetOrCreateTupleType({&MapReferenceType, KeyType.Get()}),
GetOrCreateReferenceType(ValueType.Get(), ValueType.Get()),
TransactsDecidesEffectSet,
{KeyType.Get(), ValueType.Get()},
true);
_WeakMapRefCallOp->_NegativeType = &FunctionType;
_WeakMapRefCallOp->_Signature = SSignature(FunctionType, {
_WeakMapRefCallOp->CreateDataDefinition(_Symbols->AddChecked("Map"), &MapReferenceType),
_WeakMapRefCallOp->CreateDataDefinition(_Symbols->AddChecked("Key"), KeyType.Get())});
_WeakMapRefCallOp->SetAccessLevel({SAccessLevel::EKind::Public});
_WeakMapRefCallOp->AddAttributeClass(_intrinsicClass);
}
{
// @code
// weak_map(t:subtype(comparable), u:type) := intrinsic{}
// @endcode
_WeakMapOp = VerseModuleBuiltInPart.CreateFunction(_IntrinsicSymbols._FuncNameWeakMap);
auto [ExplicitKeyType, KeyType, NegativeKeyType] = CreateExplicitTypeParam(
_WeakMapOp,
_Symbols->AddChecked("KeyType"),
_Symbols->AddChecked("t"),
_Symbols->AddChecked("u"),
&ComparableSubtypeType);
auto [ExplicitValueType, ValueType, NegativeValueType] = CreateExplicitTypeParam(
_WeakMapOp,
_Symbols->AddChecked("ValueType"),
_Symbols->AddChecked("v"),
_Symbols->AddChecked("w"),
_typeType);
CMapType& MapType = GetOrCreateWeakMapType(*KeyType, *ValueType);
CMapType& NegativeMapType = MapType;
const CFunctionType& FunctionType = GetOrCreateFunctionType(
GetOrCreateTupleType({ExplicitKeyType->GetType(), ExplicitValueType->GetType()}),
GetOrCreateTypeType(&MapType, &NegativeMapType),
ConvergesEffectSet,
{KeyType, NegativeKeyType, ValueType, NegativeValueType},
true);
_WeakMapOp->_NegativeType = &FunctionType;
_WeakMapOp->_Signature = SSignature(FunctionType, {
ExplicitKeyType,
ExplicitValueType});
_WeakMapOp->SetAccessLevel({SAccessLevel::EKind::Public});
_WeakMapOp->AddAttributeClass(_intrinsicClass);
}
//
// Option generics
//
{
_OptionQueryOp = VerseModuleBuiltInPart.CreateFunction(_IntrinsicSymbols._OpNameQuery);
TSRef<CTypeVariable> ValueType = _OptionQueryOp->CreateTypeVariable(
_Symbols->AddChecked("t"),
_typeType,
_typeType);
COptionType& OptionType = GetOrCreateOptionType(ValueType.Get());
const CFunctionType& FunctionType = GetOrCreateFunctionType(
OptionType,
*ValueType,
ConvergesDecidesEffectSet,
{ValueType.Get()},
true);
_OptionQueryOp->_NegativeType = &FunctionType;
_OptionQueryOp->_Signature = SSignature(
FunctionType,
{_OptionQueryOp->CreateDataDefinition(ValName, &OptionType)});
_OptionQueryOp->SetAccessLevel({SAccessLevel::EKind::Public});
_OptionQueryOp->AddAttributeClass(_intrinsicClass);
}
//
// `FitsInPlayer`
//
{
const CTypeType& PersistableSubtypeType = GetOrCreateTypeType(&_falseType, &_persistableType);
_FitsInPlayerMap = VerseModuleBuiltInPart.CreateFunction(_IntrinsicSymbols._FuncNameFitsInPlayerMap);
TSRef<CTypeVariable> ValType = _FitsInPlayerMap->CreateTypeVariable(
_Symbols->AddChecked("t"),
&PersistableSubtypeType,
&PersistableSubtypeType);
const CFunctionType& FunctionType = GetOrCreateFunctionType(
*ValType,
*ValType,
ConvergesReadsDecidesEffectSet,
{ValType.Get()},
true);
_FitsInPlayerMap->_NegativeType = &FunctionType;
_FitsInPlayerMap->_Signature = SSignature(
FunctionType,
{_FitsInPlayerMap->CreateDataDefinition(ValName, ValType.Get())});
_FitsInPlayerMap->SetAccessLevel({SAccessLevel::EKind::Public});
_FitsInPlayerMap->AddAttributeClass(_intrinsicClass);
}
//
// getter/setter (for use in attributes)
//
{
_Getter = CreateFunction(
_Symbols->AddChecked("getter"), {{_Symbols->AddChecked("_"), &_anyType}}, *_getterClass, ComputesEffectSet
);
_Getter->SetAccessLevel({SAccessLevel::EKind::EpicInternal});
_Setter = CreateFunction(
_Symbols->AddChecked("setter"), {{_Symbols->AddChecked("_"), &_anyType}}, *_setterClass, ComputesEffectSet
);
_Setter->SetAccessLevel({SAccessLevel::EKind::EpicInternal});
}
{
// UnsafeCast(X:any, t:type):t = intrinsic{}
_UnsafeCast = VerseModuleBuiltInPart.CreateFunction(_Symbols->AddChecked("UnsafeCast"));
auto [ExplicitType, ResultType, NegativeResultType] = CreateExplicitTypeParam(
_UnsafeCast,
_Symbols->AddChecked("T"),
_Symbols->AddChecked("t"),
_Symbols->AddChecked("u"),
_typeType
);
const CFunctionType& FunctionType = GetOrCreateFunctionType(
GetOrCreateTupleType({&_anyType, ExplicitType->GetType()}),
*ResultType,
ConvergesEffectSet,
{ResultType, NegativeResultType},
false
);
_UnsafeCast->_NegativeType = &FunctionType;
_UnsafeCast->_Signature = SSignature(
FunctionType,
{_UnsafeCast->CreateDataDefinition(_Symbols->AddChecked("Value"), &_anyType),
ExplicitType}
);
_UnsafeCast->SetAccessLevel({SAccessLevel::EKind::EpicInternal});
_UnsafeCast->AddAttributeClass(_intrinsicClass);
}
{
// PredictsGetDataValue(:any, :string):t = intrinsic{}
_PredictsGetDataValue = VerseModuleBuiltInPart.CreateFunction(_Symbols->AddChecked("PredictsGetDataValue"));
// nb: this function is implicitly specialized during semantic
// analysis (to obtain `t`)
const CFunctionType& FunctionType = GetOrCreateFunctionType(
GetOrCreateTupleType({&_anyType, _stringAlias->GetType()}),
_anyType,
ConvergesEffectSet,
{},
false
);
_PredictsGetDataValue->_NegativeType = &FunctionType;
_PredictsGetDataValue->_Signature = SSignature(
FunctionType,
{_PredictsGetDataValue->CreateDataDefinition(_Symbols->AddChecked("Object"), &_anyType),
_PredictsGetDataValue->CreateDataDefinition(_Symbols->AddChecked("FieldName"), _stringAlias->GetType())}
);
_PredictsGetDataValue->SetAccessLevel({SAccessLevel::EKind::EpicInternal});
_PredictsGetDataValue->AddAttributeClass(_intrinsicClass);
}
{
// PredictsGetDataRef(:any, :string):ref t = intrinsic{}
// nb: this function is implicitly specialized during semantic
// analysis (to obtain `t`)
_PredictsGetDataRef = VerseModuleBuiltInPart.CreateFunction(_Symbols->AddChecked("PredictsGetDataRef"));
const CFunctionType& FunctionType = GetOrCreateFunctionType(
GetOrCreateTupleType({&_anyType, _stringAlias->GetType()}),
_anyType,
ConvergesEffectSet,
{},
false
);
_PredictsGetDataRef->_NegativeType = &FunctionType;
_PredictsGetDataRef->_Signature = SSignature(
FunctionType,
{_PredictsGetDataRef->CreateDataDefinition(_Symbols->AddChecked("Object"), &_anyType),
_PredictsGetDataRef->CreateDataDefinition(_Symbols->AddChecked("FieldName"), _stringAlias->GetType())}
);
_PredictsGetDataRef->SetAccessLevel({SAccessLevel::EKind::EpicInternal});
_PredictsGetDataRef->AddAttributeClass(_intrinsicClass);
}
//
// Intrinsic data definitions
//
//
// Floats
//
{
const CFloatType& InfType = GetOrCreateConstrainedFloatType(INFINITY, INFINITY);
_InfDefinition = VerseModuleBuiltInPart.CreateDataDefinition(_IntrinsicSymbols._Inf, &InfType);
_InfDefinition->_NegativeType = &InfType;
_InfDefinition->SetAccessLevel({SAccessLevel::EKind::Public});
_InfDefinition->AddAttributeClass(_intrinsicClass);
}
{
const CFloatType& NaNType = GetOrCreateConstrainedFloatType(NAN, NAN);
_NaNDefinition = VerseModuleBuiltInPart.CreateDataDefinition(_IntrinsicSymbols._NaN, &NaNType);
_NaNDefinition->_NegativeType = &NaNType;
_NaNDefinition->SetAccessLevel({SAccessLevel::EKind::Public});
_NaNDefinition->AddAttributeClass(_intrinsicClass);
}
}
void CSemanticProgram::PopulateEffectDescriptorTable()
{
ULANG_ASSERTF(!bEffectsTablePopulated, "Reinitializing the effects table is not allowed!");
bEffectsTablePopulated = true;
// Effect Key EffectSet to apply Effect bits to rescind before applying effect Effect classes that can't coexist or are considered redundant with the key class Allow in decomposition
_EffectDescriptorTable.Insert(_readsClass, { EffectSets::Reads, EEffect::reads | EEffect::writes | EEffect::allocates | EEffect::no_rollback | EEffect::dictates, { _transactsClass } });
_EffectDescriptorTable.Insert(_writesClass, { EffectSets::Writes, EEffect::reads | EEffect::writes | EEffect::allocates | EEffect::no_rollback | EEffect::dictates, { _transactsClass } });
_EffectDescriptorTable.Insert(_allocatesClass, { EffectSets::Allocates, EEffect::reads | EEffect::writes | EEffect::allocates | EEffect::no_rollback | EEffect::dictates, { _transactsClass, _variesClassDeprecated } });
_EffectDescriptorTable.Insert(_transactsClass, { EffectSets::Transacts, EEffect::reads | EEffect::writes | EEffect::allocates | EEffect::no_rollback | EEffect::dictates, { _readsClass, _writesClass, _allocatesClass, _variesClassDeprecated, _computesClass, _convergesClass } });
_EffectDescriptorTable.Insert(_computesClass, { EffectSets::Computes, EEffect::diverges | EEffect::reads | EEffect::writes | EEffect::allocates | EEffect::no_rollback | EEffect::dictates, { _transactsClass, _variesClassDeprecated, _convergesClass } });
_EffectDescriptorTable.Insert(_convergesClass, { EffectSets::Converges, EEffect::diverges | EEffect::reads | EEffect::writes | EEffect::allocates | EEffect::no_rollback | EEffect::dictates, { _transactsClass, _variesClassDeprecated, _computesClass } });
_EffectDescriptorTable.Insert(_suspendsClass, { EffectSets::Suspends, EEffect::suspends, {} });
_EffectDescriptorTable.Insert(_decidesClass, { EffectSets::Decides, EEffect::decides, {} });
_EffectDescriptorTable.Insert(_predictsClass, { {}, EEffect::dictates, {} });
_EffectDescriptorTable.Insert(_variesClassDeprecated, { EffectSets::VariesDeprecated, EEffect::reads | EEffect::writes | EEffect::allocates | EEffect::no_rollback, { _transactsClass, _allocatesClass, _computesClass, _convergesClass }, false });
// Create any legacy effects tables that might come up
{
// Duplicate the latest table and augment the meaning of decides to imply diverges as this aligns with the legacy effects (pre-CL33775275)
for (const TKeyValuePair<const CClass*, SEffectDescriptor>& DescPair : _EffectDescriptorTable)
{
_EffectDescriptorTable_Pre3100.Insert(DescPair._Key, DescPair._Value);
}
_EffectDescriptorTable_Pre3100[_decidesClass]._EffectSet |= EffectSets::Computes;
}
for (const TKeyValuePair<const CClass*, SEffectDescriptor>& DescPair : _EffectDescriptorTable)
{
_AllEffectClasses.Add(DescPair._Key);
}
for (const TKeyValuePair<const CClass*, SEffectDescriptor>& DescPair : _EffectDescriptorTable)
{
if (DescPair._Value._AllowInDecomposition)
{
_OrderedEffectDecompositionData.Add({ DescPair._Value._EffectSet, DescPair._Key });
}
}
{
// (Stable!-)Sort the decomp table to give us the heaviest effect classes (eg. transacts) first.
// This will naturally favor the aggregate effect classes over many singles - ie. <transacts> instead of something like <reads><writes><allocates><computes>
_OrderedEffectDecompositionData.StableSort([](const SDecompositionMapping& A, const SDecompositionMapping& B)
{
if (A.Effects.Num() == B.Effects.Num())
{
// alphabetical sorting is important because this code is indirectly used in mangled symbol generation
return A.Class->Definition()->AsNameStringView() < B.Class->Definition()->AsNameStringView();
}
return A.Effects.Num() > B.Effects.Num();
});
for (int32_t I = 0; I < _OrderedEffectDecompositionData.Num(); ++I)
{
const SDecompositionMapping& Mapping = _OrderedEffectDecompositionData[I];
_OrderedEffectDecompositionDataIndexFromClass.Insert(Mapping.Class, I);
}
}
ValidateEffectDescriptorTable(_EffectDescriptorTable);
ValidateEffectDescriptorTable(_EffectDescriptorTable_Pre3100);
}
void CSemanticProgram::ValidateEffectDescriptorTable(const TMap<const CClass*, SEffectDescriptor>& DescriptorTable) const
{
ULANG_ASSERTF(bEffectsTablePopulated, "Effects descriptor table not populated!");
for (const auto& DescPair : DescriptorTable)
{
const CClass* SourceClass = DescPair._Key;
const SEffectDescriptor& SourceDescriptor = DescPair._Value;
ULANG_ASSERTF(SourceClass != nullptr, "Null keys are not allowed inside the effect descriptor table");
for (const CClass* TargetClass : SourceDescriptor._MutualExclusions)
{
ULANG_ASSERTF(TargetClass != nullptr, "Null references are not allowed inside the effect descriptor table - mutual exclusion list for `%s`", SourceClass->Definition()->AsNameCString());
ULANG_ASSERTF(SourceClass != TargetClass, "Effect classes cannot be mutually exclusive with themselves - `%s`", SourceClass->Definition()->AsNameCString());
const SEffectDescriptor* TargetDescriptor = DescriptorTable.Find(TargetClass);
ULANG_ASSERTF(TargetDescriptor != nullptr, "All mutually exclusive effect classes must also have a descriptor in the table - `%s` is missing", TargetClass->Definition()->AsNameCString());
ULANG_ASSERTF(TargetDescriptor->_MutualExclusions.Contains(SourceClass), "All mutual exclusion relationships must be reciprocated - `%s` lacks `%s`", TargetClass->Definition()->AsNameCString(), SourceClass->Definition()->AsNameCString());
}
ULANG_ASSERTF(_AllEffectClasses.Contains(SourceClass), "All effect classes must be in both the descriptor table and the all-effects list", SourceClass->Definition()->AsNameCString());
}
for (const CClass* EffectClass : _AllEffectClasses)
{
ULANG_ASSERTF(DescriptorTable.Contains(EffectClass), "All effect classes must be in both the descriptor table and the all-effects list", EffectClass->Definition()->AsNameCString());
}
}
const TMap<const CClass*, SEffectDescriptor>& CSemanticProgram::GetEffectDescriptorTableForVersion(uint32_t UploadedAtFNVersion) const
{
if (!VerseFN::UploadedAtFNVersion::DecidesEffectNoLongerImpliesComputes(UploadedAtFNVersion))
{
return _EffectDescriptorTable_Pre3100;
}
return _EffectDescriptorTable;
}
const SEffectDescriptor& CSemanticProgram::FindEffectDescriptorChecked(const CClass* effectClass, uint32_t UploadedAtFNVersion /*= Latest*/ ) const
{
const SEffectDescriptor* ResultDescriptor = GetEffectDescriptorTableForVersion(UploadedAtFNVersion).Find(effectClass);
ULANG_ASSERTF(ResultDescriptor != nullptr, "Failed to find an effect descriptor for the `%s` effect class", effectClass->Definition()->AsNameCString());
return *ResultDescriptor;
}
TOptional<SEffectSet> CSemanticProgram::ConvertEffectClassesToEffectSet(
const TArray<const CClass*>& EffectClasses,
const SEffectSet& DefaultEffectSet,
SConvertEffectClassesToEffectSetError* OutError /*= nullptr*/,
uint32_t UploadedAtFNVersion /*=Latest*/) const
{
ULANG_ASSERTF(bEffectsTablePopulated, "Effects descriptor table not populated!");
bool bFoundError{};
// Check that all these effect classes can coexist
for (int I = 0; I < EffectClasses.Num(); ++I)
{
const uLang::SEffectDescriptor& OuterDesc = FindEffectDescriptorChecked(EffectClasses[I], UploadedAtFNVersion);
for (int J = I + 1; J < EffectClasses.Num(); ++J)
{
if (OuterDesc._MutualExclusions.Contains(EffectClasses[J]))
{
if (OutError)
{
OutError->InvalidPairs.Add({EffectClasses[I], EffectClasses[J]});
}
if (!bFoundError)
{
bFoundError = true;
}
}
}
}
SEffectSet Result = DefaultEffectSet;
SEffectSet AddedEffects = SEffectSet{};
const TMap<const CClass*, SEffectDescriptor>& EffectDescriptorTable = GetEffectDescriptorTableForVersion(UploadedAtFNVersion);
for (const CClass* EffectClass : EffectClasses)
{
if (const uLang::SEffectDescriptor* EffectDesc = EffectDescriptorTable.Find(EffectClass))
{
Result &= ~EffectDesc->_RescindFromDefault;
AddedEffects |= EffectDesc->_EffectSet;
}
}
if (EffectClasses.Contains(_predictsClass))
{
Result &= ~EffectSets::Dictates;
AddedEffects &= ~EffectSets::Dictates;
}
Result |= AddedEffects;
if (bFoundError)
{
if (OutError)
{
OutError->ResultSet = Result;
}
return {};
}
return Result;
}
// Convert an effect set into a set of code-side effect classes
TOptional<TArray<const CClass*>> CSemanticProgram::ConvertEffectSetToEffectClasses(
const SEffectSet& TargetSet,
const SEffectSet& DefaultEffectSet) const
{
ULANG_ASSERTF(
bEffectsTablePopulated,
"Effects descriptor table must be populated before calling this function.");
if (TArray<const CClass*>* Cached = _CachedEffectSetToEffectClasses.Find({TargetSet, DefaultEffectSet}))
{
return {*Cached};
}
auto&& ProducesTargetSet = [&](const TArray<const CClass*>& Candidate)
{
// It is currently not necessary to support the Effect-set to Classes conversion with
// versioned effect tables. That's only used for digest creation and some
// current-version-only cases like the LSP.
const TOptional<SEffectSet> CandidateSet =
ConvertEffectClassesToEffectSet(Candidate, DefaultEffectSet, nullptr, VerseFN::UploadedAtFNVersion::Latest);
return CandidateSet && *CandidateSet == TargetSet;
};
TOptional<TArray<const CClass*>> Result;
TArray<const CClass*> Candidates;
TFunction<void(int32_t)> Search = [&](int32_t I)
{
if (I == _OrderedEffectDecompositionData.Num())
{
if (ProducesTargetSet(Candidates) && (!Result || Candidates.Num() < Result->Num()))
{
Result = {Candidates};
}
return;
}
const CClass* Class = _OrderedEffectDecompositionData[I].Class;
// try without Class:
Search(I + 1);
// try with Class:
Candidates.Push(Class);
Search(I + 1);
Candidates.Pop();
};
Search(0);
if (Result)
{
// the above algorithm isn't stable, so we have to sort the result according to the effect
// classes' order of appearance in _OrderedEffectDecompositionData:
auto&& OrderedIndexOf = [&](const CClass& Class) -> int32_t
{
const int32_t* I = _OrderedEffectDecompositionDataIndexFromClass.Find(&Class);
ULANG_ASSERT(I);
return *I;
};
Result->StableSort([&](const CClass& A, const CClass& B)
{
return OrderedIndexOf(A) < OrderedIndexOf(B);
});
_CachedEffectSetToEffectClasses.Insert({TargetSet, DefaultEffectSet}, *Result);
}
return Result;
}
CDefinition* CSemanticProgram::FindDefinitionByVersePathInternal(CUTF8StringView VersePath) const
{
const CLogicalScope* Scope = this;
CDefinition* Result = nullptr;
bool bError = false;
FilePathUtils::ForeachPartOfPath(VersePath, [this, &VersePath, &Scope, &Result, &bError](const uLang::CUTF8StringView& Part)
{
if (Part.IsFilled() && !bError)
{
TOptional<CSymbol> PartSymbol = _Symbols->Find(Part);
if (!PartSymbol)
{
bError = true;
}
else
{
for (CDefinition* Definition : Scope->GetDefinitions())
{
if (Definition->GetName() == PartSymbol)
{
// Is this the leaf of the VersePath?
if (Part._End == VersePath._End)
{
// Yes, then that's the definition we want
Result = Definition;
}
else if (CModule* Module = Definition->AsNullable<CModule>())
{
// Otherwise it better be a module
Scope = Module;
}
else
{
bError = true;
}
break;
}
}
}
}
});
return Result;
}
#if WITH_VERSE_BPVM
// A tracking structure for profile-time data defined as a mirror of FProfileLocus
const CTupleType* CSemanticProgram::GetProfileLocusType()
{
if (!_ProfileLocusType)
{
_ProfileLocusType = &GetOrCreateTupleType(
{
_intType, // BeginRow
_intType, // BeginColumn
_intType, // EndRow
_intType, // EndColumn
_stringAlias->GetType() // SnippetName
});
}
return _ProfileLocusType;
}
// A tracking structure for profile-time data defined as a mirror of FSolarisProfilingData
const CTupleType* CSemanticProgram::GetProfileDataType()
{
if (!_ProfileDataType)
{
if (const CTypeBase* ProfileLocusType = GetProfileLocusType())
{
_ProfileDataType = &GetOrCreateTupleType(
{
_intType, // WallTimeStart
ProfileLocusType, // Locus
});
}
}
return _ProfileDataType;
}
#endif // WITH_VERSE_BPVM
} // namespace uLang