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

2093 lines
72 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "uLang/Semantics/Expression.h"
#include "uLang/Common/Containers/SharedPointer.h"
#include "uLang/Common/Containers/SharedPointerArray.h"
#include "uLang/Semantics/ModuleAlias.h"
#include "uLang/Semantics/ScopedAccessLevelType.h"
#include "uLang/Semantics/SemanticEnumeration.h"
#include "uLang/Semantics/SemanticFunction.h"
#include "uLang/Semantics/SemanticProgram.h"
#include "uLang/Semantics/SemanticTypes.h"
#include "uLang/Semantics/TypeAlias.h"
#include "uLang/Semantics/TypeVariable.h"
#include "uLang/Semantics/UnknownType.h"
#include "uLang/SourceProject/PackageRole.h"
#include "uLang/Syntax/VstNode.h"
namespace uLang
{
SAstNodeTypeInfo GetAstNodeTypeInfo(EAstNodeType NodeType)
{
switch(NodeType)
{
#define VISIT_AST_NODE_TYPE(Name, Class) case EAstNodeType::Name: return {#Name, #Class};
VERSE_VISIT_AST_NODE_TYPES(VISIT_AST_NODE_TYPE)
#undef VISIT_AST_NODE_TYPE
default: ULANG_UNREACHABLE();
};
}
//=======================================================================================
// CAstNode Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CAstNode::~CAstNode()
{
if (IsVstMappingReciprocal())
{
if (_MappedVstNode && _MappedVstNode->_MappedAstNode == this)
{
_MappedVstNode->_MappedAstNode = nullptr;
}
}
}
//=======================================================================================
// CExpressionBase Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
const CTypeBase* CExpressionBase::GetResultType(const CSemanticProgram& Program) const
{
return _Report.IsSet()
? _Report.GetValue().ResultType
: nullptr;
}
//---------------------------------------------------------------------------------------
void CExpressionBase::SetResultType(const CTypeBase* InResultType)
{
ULANG_ENSUREF(!_Report.IsSet(), "Node was previously analyzed!");
ULANG_ENSUREF(InResultType!=nullptr, "Type must be non-null");
_Report = SAnalysisResult{ InResultType };
}
void CExpressionBase::RefineResultType(const CTypeBase* RefinedResultType)
{
ULANG_ENSUREF(_Report.IsSet(), "Node was not previously analyzed!");
ULANG_ENSUREF(RefinedResultType != nullptr, "RefinedType must be non-null");
// TODO: We should check IsSubtype(_Report.GetValue(), RefinedResultType) but then we'd need to take a scope here.
_Report = SAnalysisResult { RefinedResultType };
}
//=======================================================================================
// CExprCompoundBase Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
bool CExprCompoundBase::CanFail(const CAstPackage* Package) const
{
for (CExpressionBase* SubExpr : _SubExprs)
{
if (SubExpr->CanFail(Package))
{
return true;
}
}
return false;
}
//---------------------------------------------------------------------------------------
const CExpressionBase* CExprCompoundBase::FindFirstAsyncSubExpr(const CSemanticProgram& Program) const
{
const CExpressionBase* AsyncExpr;
for (CExpressionBase* SubExpr : _SubExprs)
{
AsyncExpr = SubExpr->FindFirstAsyncSubExpr(Program);
if (AsyncExpr)
{
return AsyncExpr;
}
}
return nullptr;
}
//---------------------------------------------------------------------------------------
bool CExprCompoundBase::operator==(const CExpressionBase& Other) const
{
return BaseCompare(*this, Other)
&& AreSubExprsEqual(_SubExprs, static_cast<const CExprCompoundBase&>(Other)._SubExprs);
}
//=======================================================================================
// CExprExternal Methods
//=======================================================================================
CExprExternal::CExprExternal(const CSemanticProgram& Program)
: CExpressionBase(&Program._falseType)
{
}
//=======================================================================================
// CExprLogic Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CExprLogic::CExprLogic(const CSemanticProgram& Program, bool Value)
: CExpressionBase(&Program._logicType)
, _Value(Value)
{}
//=======================================================================================
// CExprNumber Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CExprNumber::CExprNumber(CSemanticProgram& Program, Integer IntValue)
: _IntValue(IntValue)
, _bIsFloat(false)
{
SetResultType(&Program.GetOrCreateConstrainedIntType(IntValue, IntValue));
}
CExprNumber::CExprNumber(CSemanticProgram& Program, Float FloatValue)
: _FloatValue(FloatValue)
, _bIsFloat(true)
{
SetResultType(&Program.GetOrCreateConstrainedFloatType(FloatValue, FloatValue));
}
void CExprNumber::SetIntValue(CSemanticProgram& Program, Integer IntValue)
{
_IntValue = IntValue;
_bIsFloat = false;
SetResultType(&Program.GetOrCreateConstrainedIntType(IntValue, IntValue));
}
void CExprNumber::SetFloatValue(CSemanticProgram& Program, Float FloatValue)
{
_FloatValue = FloatValue;
_bIsFloat = true;
SetResultType(&Program.GetOrCreateConstrainedFloatType(FloatValue, FloatValue));
}
//=======================================================================================
// CExprEnumLiteral Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
const CTypeBase* CExprEnumLiteral::GetResultType(const CSemanticProgram& Program) const
{
ULANG_ASSERT(_Enumerator);
return _Enumerator->_Enumeration;
}
void CExprEnumLiteral::VisitImmediates(SAstVisitor& Visitor) const
{
CExpressionBase::VisitImmediates(Visitor);
Visitor.VisitImmediate("Enumerator", _Enumerator->AsCode());
}
const CDefinition* CExprEnumLiteral::IdentifierDefinition() const
{
return _Enumerator->_EnclosingScope.ScopeAsDefinition();
}
//=======================================================================================
// CExprDefinition Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
bool CExprDefinition::operator==(const CExpressionBase& Other) const
{
if (Other.GetNodeType() == EAstNodeType::Definition)
{
const CExprDefinition& OthrDef = static_cast<const CExprDefinition&>(Other);
const CExprDefinition& ThisDef = *this;
return Other.GetNodeType() == EAstNodeType::Definition
&& (ThisDef._Name == OthrDef._Name)
&& (IsSubExprEqual(ThisDef.Element(), OthrDef.Element()))
&& (IsSubExprEqual(ThisDef.ValueDomain(), OthrDef.ValueDomain()))
&& (IsSubExprEqual(ThisDef.Value(), OthrDef.Value()));
}
else
{
return false;
}
}
//---------------------------------------------------------------------------------------
bool CExprDefinition::CanFail(const CAstPackage* Package) const
{
return Value() && Value()->CanFail(Package);
}
//---------------------------------------------------------------------------------------
const CExpressionBase* CExprDefinition::FindFirstAsyncSubExpr(const CSemanticProgram& Program) const
{
return Value()
? Value()->FindFirstAsyncSubExpr(Program)
: nullptr;
}
//=======================================================================================
// CExprIdentifierClass Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CExprIdentifierClass::CExprIdentifierClass(const CTypeType* Type, TSPtr<CExpressionBase>&& Context, TSPtr<CExpressionBase>&& Qualifier)
: CExprIdentifierBase(Move(Context), Move(Qualifier))
{
SetResultType(Type);
}
//---------------------------------------------------------------------------------------
const CTypeType* CExprIdentifierClass::GetTypeType(const CSemanticProgram& Program) const
{
return &GetResultType(Program)->GetNormalType().AsChecked<CTypeType>();
}
const CClass* CExprIdentifierClass::GetClass(const CSemanticProgram& Program) const
{
const CTypeType* TypeType = GetTypeType(Program);
return &TypeType->PositiveType()->GetNormalType().AsChecked<CClass>();
}
CUTF8String CExprIdentifierClass::GetErrorDesc() const
{
if (const CTypeBase* ResultType = IrGetResultType())
{
return ResultType->AsCode();
}
else
{
return "class identifier";
}
}
//=======================================================================================
// CExprIdentifierModule Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CExprIdentifierModule::CExprIdentifierModule(const CModule* Module, TSPtr<CExpressionBase>&& Context, TSPtr<CExpressionBase>&& Qualifier)
: CExprIdentifierBase(Move(Context), Move(Qualifier))
{
SetResultType(Module);
}
//---------------------------------------------------------------------------------------
CModule const* CExprIdentifierModule::GetModule(const CSemanticProgram& Program) const
{
return &GetResultType(Program)->GetNormalType().AsChecked<CModule>();
}
//=======================================================================================
// CExprEnumerationType Methods
//=======================================================================================
const CTypeType* CExprEnumerationType::GetTypeType(const CSemanticProgram& Program) const
{
return &GetResultType(Program)->GetNormalType().AsChecked<CTypeType>();
}
CEnumeration const* CExprEnumerationType::GetEnumeration(const CSemanticProgram& Program) const
{
const CTypeType* TypeType = GetTypeType(Program);
return &TypeType->PositiveType()->GetNormalType().AsChecked<CEnumeration>();
}
//=======================================================================================
// CExprInterfaceType Methods
//=======================================================================================
CInterface const* CExprInterfaceType::GetInterface(const CSemanticProgram& Program) const
{
const CTypeType* TypeType = GetTypeType(Program);
return &TypeType->PositiveType()->GetNormalType().AsChecked<CInterface>();
}
//=======================================================================================
// CExprIdentifierData Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CExprIdentifierData::CExprIdentifierData(const CSemanticProgram& Program, const CDataDefinition& DataDefinition, TSPtr<CExpressionBase> Context, TSPtr<CExpressionBase>&& Qualifier )
: CExprIdentifierBase(Move(Context), Move(Qualifier))
, _DataDefinition(DataDefinition)
{
}
//---------------------------------------------------------------------------------------
const CTypeBase* CExprIdentifierData::GetResultType(const CSemanticProgram& Program) const
{
const CTypeBase* DataDefinitionPositiveValueType = _DataDefinition.GetType() ? _DataDefinition.GetType() : Program.GetDefaultUnknownType();
// this identifier expression result type needs to be
// wrapped in a reference if it has a context and the
// context is a reference type
if (!Context())
{
return DataDefinitionPositiveValueType;
}
const CTypeBase* ContextType = Context()->GetResultType(Program);
if (!ContextType->GetNormalType().IsA<CReferenceType>())
{
return DataDefinitionPositiveValueType;
}
return &const_cast<CSemanticProgram&>(Program).GetOrCreateReferenceType(
_DataDefinition._NegativeType,
DataDefinitionPositiveValueType);
}
//=======================================================================================
// CExprIdentifierTypeAlias Methods
//=======================================================================================
void CExprIdentifierTypeAlias::VisitImmediates(SAstVisitor& Visitor) const
{
CExpressionBase::VisitImmediates(Visitor);
Visitor.VisitImmediate("TypeAlias", _TypeAlias);
}
CExprIdentifierTypeAlias::CExprIdentifierTypeAlias(const CTypeAlias& TypeAlias, TSPtr<CExpressionBase>&& Context /* = nullptr */, TSPtr<CExpressionBase>&& Qualifier /* = nullptr */)
: CExprIdentifierBase(Move(Context), Move(Qualifier))
, _TypeAlias(TypeAlias)
{
}
const CTypeBase* CExprIdentifierTypeAlias::GetResultType(const CSemanticProgram& Program) const
{
return _TypeAlias.GetTypeType();
}
//=======================================================================================
// CExprIdentifierTypeVariable Methods
//=======================================================================================
CExprIdentifierTypeVariable::CExprIdentifierTypeVariable(const CTypeVariable& TypeVariable, TSPtr<CExpressionBase>&& Context, TSPtr<CExpressionBase>&& Qualifier)
: CExprIdentifierBase(Move(Context), Move(Qualifier))
, _TypeVariable(TypeVariable)
{
SetResultType(&TypeVariable.GetProgram().GetOrCreateTypeType(&TypeVariable, &TypeVariable));
}
void CExprIdentifierTypeVariable::VisitImmediates(SAstVisitor& Visitor) const
{
CExpressionBase::VisitImmediates(Visitor);
Visitor.VisitImmediate("TypeVariable", _TypeVariable);
}
//=======================================================================================
// CExprIdentifierFunction Methods
//=======================================================================================
CExprIdentifierFunction::CExprIdentifierFunction(
const CFunction& Function,
TArray<SInstantiatedTypeVariable> InstTypeVariables,
const CTypeBase* ResultType,
const CTypeBase* ConstructorNegativeReturnType,
const CCaptureScope* ConstructorCaptureScope,
TSPtr<CExpressionBase>&& Context,
TSPtr<CExpressionBase>&& Qualifier,
bool bSuperQualified)
: CExprIdentifierBase(Move(Context), Move(Qualifier))
, _Function(Function)
, _InstantiatedTypeVariables(Move(InstTypeVariables))
, _ConstructorNegativeReturnType(ConstructorNegativeReturnType)
, _ConstructorCaptureScope(ConstructorCaptureScope)
, _bSuperQualified(bSuperQualified)
{
if (ResultType)
{
SetResultType(ResultType);
}
}
void CExprIdentifierFunction::VisitImmediates(SAstVisitor& Visitor) const
{
CExpressionBase::VisitImmediates(Visitor);
Visitor.VisitImmediate("Function", _Function);
Visitor.VisitImmediate("bSuperQualified", _bSuperQualified);
}
//=======================================================================================
// CExprIdentifierOverloadedFunction Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CExprIdentifierOverloadedFunction::CExprIdentifierOverloadedFunction(
TArray<const CFunction*>&& OverloadedFunctions,
bool bConstructor,
const CSymbol Symbol,
const CTypeBase* OverloadedType,
TSPtr<CExpressionBase>&& Context,
TSPtr<CExpressionBase>&& Qualifier,
const CTypeBase* Type)
: CExprIdentifierBase(Move(Context), Move(Qualifier))
, _FunctionOverloads(Move(OverloadedFunctions))
, _bConstructor(bConstructor)
, _Symbol(Symbol)
, _TypeOverload(OverloadedType)
, _bAllowUnrestrictedAccess(false)
{
SetResultType(Type);
}
void CExprIdentifierOverloadedFunction::VisitImmediates(SAstVisitor& Visitor) const
{
CExpressionBase::VisitImmediates(Visitor);
Visitor.BeginArray("FunctionOverloads", _FunctionOverloads.Num());
for (const CFunction* Function : _FunctionOverloads)
{
Visitor.VisitImmediate("", *Function);
}
Visitor.EndArray();
}
//=======================================================================================
// CExprInvocation Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
const CFunctionType* CExprInvocation::GetResolvedCalleeType() const
{
ULANG_ASSERTF(!IsIrNode() || _ResolvedCalleeType, "GetResolvedCalleeType called on unanalyzed CExprInvocation");
return _ResolvedCalleeType;
}
//---------------------------------------------------------------------------------------
const CExpressionBase* CExprInvocation::FindFirstAsyncSubExpr(const CSemanticProgram& Program) const
{
const CExpressionBase* AsyncExpr = _Callee ? _Callee->FindFirstAsyncSubExpr(Program) : nullptr;
if (AsyncExpr)
{
return AsyncExpr;
}
AsyncExpr = _Argument->FindFirstAsyncSubExpr(Program);
if (AsyncExpr)
{
return AsyncExpr;
}
if (_ResolvedCalleeType && GetResolvedCalleeType()->GetEffects()[EEffect::suspends])
{
return this;
}
return nullptr;
}
//---------------------------------------------------------------------------------------
bool CExprInvocation::CanFail(const CAstPackage* Package) const
{
// The expression may fail if any of the receiver, the arguments, or the invocation itself may fail.
if (_ResolvedCalleeType && GetResolvedCalleeType()->GetEffects()[EEffect::decides])
{
return true;
}
if (_Callee.IsValid() && _Callee->CanFail(Package))
{
return true;
}
if (_Argument.IsValid() && _Argument->CanFail(Package))
{
return true;
}
return false;
}
//---------------------------------------------------------------------------------------
bool CExprInvocation::operator==(const CExpressionBase& Other) const
{
return BaseCompare(*this, Other)
&& IsSubExprEqual(_Callee, static_cast<const CExprInvocation&>(Other)._Callee)
&& IsSubExprEqual(_Argument, static_cast<const CExprInvocation&>(Other)._Argument);
}
const CExprIdentifierFunction* GetConstructorInvocationCallee(const CExprInvocation& Invocation)
{
const TSPtr<CExpressionBase>& Callee = Invocation.GetCallee();
if (Callee->GetNodeType() != EAstNodeType::Identifier_Function)
{
return nullptr;
}
const CExprIdentifierFunction& Identifier = static_cast<const CExprIdentifierFunction&>(*Callee);
if (!Identifier._ConstructorNegativeReturnType)
{
return nullptr;
}
return &Identifier;
}
const CExprIdentifierFunction* GetConstructorInvocationCallee(const CExpressionBase& Expression)
{
if (Expression.GetNodeType() != EAstNodeType::Invoke_Invocation)
{
return nullptr;
}
return GetConstructorInvocationCallee(static_cast<const CExprInvocation&>(Expression));
}
bool IsConstructorInvocation(const CExprInvocation& Invocation)
{
return static_cast<bool>(GetConstructorInvocationCallee(Invocation));
}
bool IsConstructorInvocation(const CExpressionBase& Expression)
{
return static_cast<bool>(GetConstructorInvocationCallee(Expression));
}
//=======================================================================================
// CExprTupleElement Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
bool CExprTupleElement::operator==(const CExpressionBase& Other) const
{
if (Other.GetNodeType() != EAstNodeType::Invoke_TupleElement)
{
return false;
}
const CExprTupleElement& OtherTupleElement = static_cast<const CExprTupleElement&>(Other);
return (_ElemIdx == OtherTupleElement._ElemIdx)
&& IsSubExprEqual(_TupleExpr, OtherTupleElement._TupleExpr);
}
bool CExprTupleElement::CanFail(const CAstPackage* Package) const
{
if (!VerseFN::UploadedAtFNVersion::EnforceTupleElementExprFallibility(Package->_UploadedAtFNVersion))
{
return false;
}
return _TupleExpr->CanFail(Package) || (_ElemIdxExpr && _ElemIdxExpr->CanFail(Package));
}
//=======================================================================================
// CExprAssignment Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
bool CExprAssignment::operator==(const CExpressionBase& Other) const
{
return Other.GetNodeType() == EAstNodeType::Assignment
&& IsSubExprEqual(_Lhs, static_cast<const CExprAssignment&>(Other)._Lhs)
&& IsSubExprEqual(_Rhs, static_cast<const CExprAssignment&>(Other)._Rhs);
}
//=======================================================================================
// CExprShortCircuitAnd Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
bool CExprShortCircuitAnd::operator==(const CExpressionBase& Other) const
{
return Other.GetNodeType() == EAstNodeType::Invoke_ShortCircuitAnd
&& IsSubExprEqual(Lhs(), static_cast<const CExprShortCircuitAnd&>(Other).Lhs())
&& IsSubExprEqual(Rhs(), static_cast<const CExprShortCircuitAnd&>(Other).Rhs());
}
//=======================================================================================
// CExprShortCircuitOr Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
bool CExprShortCircuitOr::operator==(const CExpressionBase& Other) const
{
return Other.GetNodeType() == EAstNodeType::Invoke_ShortCircuitOr
&& IsSubExprEqual(Lhs(), static_cast<const CExprShortCircuitOr&>(Other).Lhs())
&& IsSubExprEqual(Rhs(), static_cast<const CExprShortCircuitOr&>(Other).Rhs());
}
//=======================================================================================
// CExprLogicalNot Methods
//=======================================================================================
const CTypeBase* CExprLogicalNot::GetResultType(const CSemanticProgram& Program) const
{
return &Program._logicType;
}
//---------------------------------------------------------------------------------------
bool CExprLogicalNot::operator==(const CExpressionBase& Other) const
{
return Other.GetNodeType() == EAstNodeType::Invoke_LogicalNot
&& IsSubExprEqual(Operand(), static_cast<const CExprLogicalNot&>(Other).Operand());
}
//=======================================================================================
// CExprComparison Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CUTF8String CExprComparison::GetErrorDesc() const
{
switch(_Op)
{
case Verse::Vst::BinaryOpCompare::op::eq: return "comparison operator '='";
case Verse::Vst::BinaryOpCompare::op::gt: return "comparison operator '>'";
case Verse::Vst::BinaryOpCompare::op::gteq: return "comparison operator '>='";
case Verse::Vst::BinaryOpCompare::op::lt: return "comparison operator '<'";
case Verse::Vst::BinaryOpCompare::op::lteq: return "comparison operator '<='";
case Verse::Vst::BinaryOpCompare::op::noteq: return "comparison operator '<>'";
default:
ULANG_UNREACHABLE();
}
}
//---------------------------------------------------------------------------------------
bool CExprComparison::operator==(const CExpressionBase& Other) const
{
return CExprInvocation::operator==(Other)
&& _Op == static_cast<const CExprComparison&>(Other)._Op;
}
//=======================================================================================
// CExprMakeOption Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
bool CExprMakeOption::operator==(const CExpressionBase& Other) const
{
return Other.GetNodeType() == EAstNodeType::Invoke_MakeOption
&& IsSubExprEqual(Operand(), static_cast<const CExprMakeOption&>(Other).Operand());
}
//=======================================================================================
// CExprMapTypeFormer Methods
//=======================================================================================
const CExpressionBase* CExprMapTypeFormer::FindFirstAsyncSubExpr(const CSemanticProgram& Program) const
{
const CExpressionBase* AsyncExpr = nullptr;
for (const TSRef<CExpressionBase>& KeyTypeAst : _KeyTypeAsts)
{
AsyncExpr = KeyTypeAst->FindFirstAsyncSubExpr(Program);
if (AsyncExpr) { return AsyncExpr; }
}
return _ValueTypeAst->FindFirstAsyncSubExpr(Program);
}
//=======================================================================================
// CExprSubtype Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CUTF8String CExprSubtype::GetErrorDesc() const
{
CUTF8String Result = GetConstraintTypeAsCString(_SubtypeConstraint, true);
return Result + "(..)";
}
const CTypeType& CExprSubtype::GetSubtypeType() const
{
ULANG_ASSERTF(_TypeType, "GetSubtypeType called on unanalyzed expression");
return *_TypeType;
}
//=======================================================================================
// CExprTupleType Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
bool CExprTupleType::operator==(const CExpressionBase& Other) const
{
if (!BaseCompare(*this, Other))
{
return false;
}
const CExprTupleType* OtherTupleType = static_cast<const CExprTupleType*>(&Other);
return (_TypeType && (_TypeType == OtherTupleType->_TypeType))
|| AreSubExprsEqual(_ElementTypeExprs, OtherTupleType->_ElementTypeExprs);
}
//=======================================================================================
// CExprMakeMap Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
bool CExprMakeMap::CanFail(const CAstPackage* Package) const
{
// This can't just call CanFail on subexpressions, because the subexpressions will be
// CExprFunctionLiteral, which doesn't propagate CanFail from its subexpressions.
for (const CExpressionBase* SubExpr : _SubExprs)
{
ULANG_ASSERTF (SubExpr->GetNodeType() == EAstNodeType::Literal_Function, "Expected subexpressions to be function literals");
const CExprFunctionLiteral* PairLiteral = static_cast<const CExprFunctionLiteral*>(SubExpr);
if (PairLiteral->Range()->CanFail(Package) || PairLiteral->Domain()->CanFail(Package))
{
return true;
}
}
return false;
}
//=======================================================================================
// CExprMakeRange Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
bool CExprMakeRange::operator==(const CExpressionBase& Other) const
{
if (Other.GetNodeType() != EAstNodeType::Invoke_MakeRange)
{
return false;
}
const CExprMakeRange& OtherCtor = static_cast<const CExprMakeRange&>(Other);
if (_Report != OtherCtor._Report)
{
return false;
}
if (_Lhs != OtherCtor._Lhs)
{
return false;
}
if (_Rhs != OtherCtor._Rhs)
{
return false;
}
return true;
}
//=======================================================================================
// CExprInvokeType Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CExprInvokeType::CExprInvokeType(const CTypeBase* NegativeType, const CTypeBase* PositiveType, bool bIsFallible, TSPtr<CExpressionBase>&& TypeAst, TSRef<CExpressionBase>&& Argument)
: _NegativeType(NegativeType), _bIsFallible(bIsFallible), _TypeAst(Move(TypeAst)), _Argument(Move(Argument))
{
// Invoking void returns false (i.e. the sole value of the type true), and all other types are identity functions.
const CSemanticProgram& Program = PositiveType->GetProgram();
if (PositiveType->GetNormalType().IsA<CVoidType>())
{
SetResultType(&Program._trueType);
}
else
{
SetResultType(PositiveType);
}
}
//---------------------------------------------------------------------------------------
const CExpressionBase* CExprInvokeType::FindFirstAsyncSubExpr(const CSemanticProgram& Program) const
{
if (const CExpressionBase* AsyncExpr = _TypeAst ? _TypeAst->FindFirstAsyncSubExpr(Program) : nullptr)
{
return AsyncExpr;
}
if (const CExpressionBase* AsyncExpr = _Argument ? _Argument->FindFirstAsyncSubExpr(Program) : nullptr)
{
return AsyncExpr;
}
return nullptr;
}
//---------------------------------------------------------------------------------------
bool CExprInvokeType::operator==(const CExpressionBase& Other) const
{
if (Other.GetNodeType() != EAstNodeType::Invoke_Type)
{
return false;
}
const CExprInvokeType& OtherInvokeType = static_cast<const CExprInvokeType&>(Other);
return _Report == OtherInvokeType._Report
&& _NegativeType == OtherInvokeType._NegativeType
&& _bIsFallible == OtherInvokeType._bIsFallible
&& _TypeAst == OtherInvokeType._TypeAst
&& _Argument == OtherInvokeType._Argument;
}
//=======================================================================================
// CExprPointerToReference Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
bool CExprPointerToReference::operator==(const CExpressionBase& Other) const
{
if (Other.GetNodeType() != EAstNodeType::Invoke_PointerToReference)
{
return false;
}
const CExprPointerToReference& OtherPointerToReference = static_cast<const CExprPointerToReference&>(Other);
if (Operand() != OtherPointerToReference.Operand())
{
return false;
}
return true;
}
//---------------------------------------------------------------------------------------
const CTypeBase* CExprPointerToReference::GetResultType(const CSemanticProgram& Program) const
{
const CTypeBase* Result = Program.GetDefaultUnknownType();
if (!Operand())
{
return Result;
}
const CTypeBase* OperandResultType = Operand()->GetResultType(Program);
if (!OperandResultType)
{
return Result;
}
const CPointerType* OperandPointerType = OperandResultType->GetNormalType().AsNullable<CPointerType>();
if (!OperandPointerType)
{
return Result;
}
const CTypeBase* NegativeValueType;
if (_bWritable)
{
NegativeValueType = OperandPointerType->NegativeValueType();
}
else
{
NegativeValueType = &Program._falseType;
}
return &const_cast<CSemanticProgram&>(Program).GetOrCreateReferenceType(
NegativeValueType,
OperandPointerType->PositiveValueType());
}
//=======================================================================================
// CExprSet Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
bool CExprSet::operator==(const CExpressionBase& Other) const
{
if (Other.GetNodeType() != EAstNodeType::Invoke_Set)
{
return false;
}
const CExprSet& OtherSet = static_cast<const CExprSet&>(Other);
if (_bIsLive != OtherSet._bIsLive)
{
return false;
}
if (!IsSubExprEqual(Operand(), OtherSet.Operand()))
{
return false;
}
return true;
}
//=======================================================================================
// CExprNewPointer Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
bool CExprNewPointer::operator==(const CExpressionBase& Other) const
{
if (Other.GetNodeType() != EAstNodeType::Invoke_NewPointer)
{
return false;
}
const CExprNewPointer& OtherNewPointer = static_cast<const CExprNewPointer&>(Other);
if (_Report != OtherNewPointer._Report)
{
return false;
}
if (_LiveScope != OtherNewPointer._LiveScope)
{
return false;
}
if (_Value != OtherNewPointer._Value)
{
return false;
}
return true;
}
//=======================================================================================
// CExprReferenceToValue Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CExprReferenceToValue::CExprReferenceToValue(TSPtr<CExpressionBase> Operand)
: CExprUnaryOp(Move(Operand))
{}
//=======================================================================================
// CExprCodeBlock Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
const CTypeBase* CExprCodeBlock::GetResultType(const CSemanticProgram& Program) const
{
return _SubExprs.IsFilled()? _SubExprs.Last()->GetResultType(Program) : &Program._trueType;
}
//=======================================================================================
// CExprLet Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
const CTypeBase* CExprLet::GetResultType(const CSemanticProgram& Program) const
{
return _SubExprs.IsFilled()? _SubExprs.Last()->GetResultType(Program) : &Program._trueType;
}
//=======================================================================================
// CExprReturn Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
const CTypeBase* CExprReturn::GetResultType(const CSemanticProgram& Program) const
{
return &Program._falseType;
}
//=======================================================================================
// CExprIf Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
const CExpressionBase* CExprIf::FindFirstAsyncSubExpr(const CSemanticProgram& Program) const
{
const CExpressionBase* AsyncExpr;
AsyncExpr = _Condition->FindFirstAsyncSubExpr(Program);
if (AsyncExpr)
{
return AsyncExpr;
}
if (_ThenClause)
{
AsyncExpr = _ThenClause->FindFirstAsyncSubExpr(Program);
if (AsyncExpr)
{
return AsyncExpr;
}
}
if (_ElseClause)
{
AsyncExpr = _ElseClause->FindFirstAsyncSubExpr(Program);
if (AsyncExpr)
{
return AsyncExpr;
}
}
return nullptr;
}
//---------------------------------------------------------------------------------------
bool CExprIf::CanFail(const CAstPackage* Package) const
{
return (_ThenClause && _ThenClause->CanFail(Package))
|| (_ElseClause && _ElseClause->CanFail(Package));
}
//---------------------------------------------------------------------------------------
bool CExprIf::operator==(const CExpressionBase& Other) const
{
if (Other.GetNodeType() != EAstNodeType::Flow_If)
{
return false;
}
const CExprIf& OtherIf = static_cast<const CExprIf&>(Other);
return _Condition == OtherIf._Condition
&& _ThenClause == OtherIf._ThenClause
&& _ElseClause == OtherIf._ElseClause;
}
//=======================================================================================
// CExprIteration Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
const CExpressionBase* CExprIteration::FindFirstAsyncSubExpr(const CSemanticProgram& Program) const
{
for (CExpressionBase* Filter : _Filters)
{
const CExpressionBase* AsyncExpr = Filter->FindFirstAsyncSubExpr(Program);
if (AsyncExpr)
{
return AsyncExpr;
}
}
return _Body.IsValid() ? _Body->FindFirstAsyncSubExpr(Program) : nullptr;
}
//---------------------------------------------------------------------------------------
bool CExprIteration::operator==(const CExpressionBase& Other) const
{
if (Other.GetNodeType() != GetNodeType())
{
return false;
}
const CExprIteration& OtherIteration = static_cast<const CExprIteration&>(Other);
if (_Filters.Num() != OtherIteration._Filters.Num())
{
return false;
}
for (int32_t FilterIndex = 0; FilterIndex < _Filters.Num(); ++FilterIndex)
{
if (!IsSubExprEqual(_Filters[FilterIndex], OtherIteration._Filters[FilterIndex]))
{
return false;
}
}
if (!IsSubExprEqual(_Body, OtherIteration._Body) ||
OtherIteration._AssociatedScope.IsValid() != _AssociatedScope.IsValid())
{
return false;
}
if (_AssociatedScope)
{
const TArray<TSRef<CDefinition>>& ItDefs = _AssociatedScope->GetDefinitions();
const TArray<TSRef<CDefinition>>& OtherItDefs = OtherIteration._AssociatedScope->GetDefinitions();
if (ItDefs.Num() != OtherItDefs.Num())
{
return false;
}
for (int32_t DefIndex = 0; DefIndex < ItDefs.Num(); ++DefIndex)
{
if (ItDefs[DefIndex] != OtherItDefs[DefIndex])
{
return false;
}
}
}
return true;
}
//=======================================================================================
// CIrArrayAdd Methods
//=======================================================================================
bool CIrArrayAdd::operator==(const CExpressionBase& Other) const
{
if (Other.GetNodeType() != GetNodeType())
{
return false;
}
const CIrArrayAdd& OtherArrayAdd = static_cast<const CIrArrayAdd&>(Other);
return *_Source == *OtherArrayAdd._Source;
}
//=======================================================================================
// CIrMapAdd Methods
//=======================================================================================
bool CIrMapAdd::operator==(const CExpressionBase& Other) const
{
if (Other.GetNodeType() != GetNodeType())
{
return false;
}
const CIrMapAdd& OtherMapAdd = static_cast<const CIrMapAdd&>(Other);
return
*_Key == *OtherMapAdd._Key &&
*_Value == *OtherMapAdd._Value;
}
const CExpressionBase* CIrMapAdd::FindFirstAsyncSubExpr(const CSemanticProgram& Program) const
{
if (const CExpressionBase* Result = _Key->FindFirstAsyncSubExpr(Program))
{
return Result;
}
return _Value->FindFirstAsyncSubExpr(Program);
}
bool CIrMapAdd::CanFail(const CAstPackage* Package) const
{
return _Key->CanFail(Package) || _Value->CanFail(Package);
}
void CIrMapAdd::VisitChildren(SAstVisitor& Visitor) const
{
Visitor.Visit("Key", _Key);
Visitor.Visit("Value", _Value);
}
//=======================================================================================
// CIrArrayUnsafeCall Methods
//=======================================================================================
bool CIrArrayUnsafeCall::operator==(const CExpressionBase& Other) const
{
if (Other.GetNodeType() != GetNodeType())
{
return false;
}
const CIrArrayUnsafeCall& OtherArrayUnsafeCall = static_cast<const CIrArrayUnsafeCall&>(Other);
return
*_Callee == *OtherArrayUnsafeCall._Callee &&
*_Argument == *OtherArrayUnsafeCall._Argument;
}
//=======================================================================================
// CIrConvertToDynamic Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CIrConvertToDynamic::CIrConvertToDynamic(const CTypeBase* ResultType, TSRef<CExpressionBase>&& Operand)
: CExprUnaryOp(Move(Operand), EVstMappingType::Ir)
{
IrSetResultType(ResultType);
}
//=======================================================================================
// CIrConvertToDynamic Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CIrConvertFromDynamic::CIrConvertFromDynamic(const CTypeBase* ResultType, TSRef<CExpressionBase>&& Operand)
: CExprUnaryOp(Move(Operand), EVstMappingType::Ir)
{
IrSetResultType(ResultType);
}
//=======================================================================================
// CIrFor Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
const CExpressionBase* CIrFor::FindFirstAsyncSubExpr(const CSemanticProgram& Program) const
{
const CExpressionBase* AsyncExpr = _Definition->FindFirstAsyncSubExpr(Program);
if (AsyncExpr)
{
return AsyncExpr;
}
return _Body.IsValid() ? _Body->FindFirstAsyncSubExpr(Program) : nullptr;
}
//---------------------------------------------------------------------------------------
bool CIrFor::operator==(const CExpressionBase& Other) const
{
if (Other.GetNodeType() != GetNodeType())
{
return false;
}
const CIrFor& OtherFor = static_cast<const CIrFor&>(Other);
if (!IsSubExprEqual(*_Definition, *OtherFor._Definition) ||
!IsSubExprEqual(_Body, OtherFor._Body) ||
OtherFor._AssociatedScope.IsValid() != _AssociatedScope.IsValid())
{
return false;
}
if (_AssociatedScope)
{
const TArray<TSRef<CDefinition>>& ItDefs = _AssociatedScope->GetDefinitions();
const TArray<TSRef<CDefinition>>& OtherItDefs = OtherFor._AssociatedScope->GetDefinitions();
if (ItDefs.Num() != OtherItDefs.Num())
{
return false;
}
for (int32_t DefIndex = 0; DefIndex < ItDefs.Num(); ++DefIndex)
{
if (ItDefs[DefIndex] != OtherItDefs[DefIndex])
{
return false;
}
}
}
return true;
}
//=======================================================================================
// CIrForBody Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
const CExpressionBase* CIrForBody::FindFirstAsyncSubExpr(const CSemanticProgram& Program) const
{
return _Body.IsValid() ? _Body->FindFirstAsyncSubExpr(Program) : nullptr;
}
//---------------------------------------------------------------------------------------
bool CIrForBody::operator==(const CExpressionBase& Other) const
{
if (Other.GetNodeType() != GetNodeType())
{
return false;
}
const CIrForBody& OtherForBody = static_cast<const CIrForBody&>(Other);
return IsSubExprEqual(_Body, OtherForBody._Body);
}
//=======================================================================================
// CExprArchetypeInstantiation Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CExprArchetypeInstantiation::CExprArchetypeInstantiation(TSRef<CExpressionBase>&& ClassAst, CExprMacroCall::CClause&& BodyAst, const CTypeBase* ResultType, const bool bIsDynamicConcreteType)
: CExpressionBase(ResultType)
, _ClassAst(Move(ClassAst))
, _BodyAst(Move(BodyAst))
, _bIsDynamicConcreteType(bIsDynamicConcreteType)
{
ULANG_ASSERTF(ResultType->GetNormalType().IsA<CClass>() || ResultType->GetNormalType().IsA<CInterface>(), "Expected result type to be a class or interface");
}
const CNominalType* CExprArchetypeInstantiation::GetClassOrInterface(const CSemanticProgram& Program) const
{
const CTypeBase* ResultType = GetResultType(Program);
if (const CInterface* ResultInterface = ResultType->GetNormalType().AsNullable<CInterface>())
{
return ResultInterface;
}
return &ResultType->GetNormalType().AsChecked<CClass>();
}
bool CExprArchetypeInstantiation::operator==(const CExpressionBase& Other) const
{
if (!BaseCompare(*this, Other))
{
return false;
}
const CExprArchetypeInstantiation& OtherInstantiation = static_cast<const CExprArchetypeInstantiation&>(Other);
if (!IsSubExprEqual(_ClassAst.Get(), OtherInstantiation._ClassAst.Get()))
{
return false;
}
if (!AreSubExprsEqual(_Arguments, OtherInstantiation._Arguments))
{
return false;
}
return true;
}
//=======================================================================================
// CExprBreak Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
const CTypeBase* CExprBreak::GetResultType(const CSemanticProgram& Program) const
{
return &Program._falseType;
}
//=======================================================================================
// CExprSnippet Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
const uLang::CTypeBase* CExprSnippet::GetResultType(const CSemanticProgram& Program) const
{
return &Program._trueType;
}
//=======================================================================================
// CExprModuleDefinition Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CExprModuleDefinition::CExprModuleDefinition(CModulePart& Module, TArray<TSRef<CExpressionBase>>&& Members)
: CMemberDefinitions(Move(Members))
, _Name(Module.GetModule()->AsNameStringView())
, _SemanticModule(&Module)
{
// This constructor is not used when creating IR
ULANG_ASSERTF(Module.GetAstNode() == nullptr, "Expected reciprocal pairing with AST node");
Module.SetAstNode(this);
}
//---------------------------------------------------------------------------------------
CExprModuleDefinition::~CExprModuleDefinition()
{
if (_SemanticModule)
{
if (IsIrNode())
{
ULANG_ASSERTF(_SemanticModule->GetIrNode(true) == this, "Expected reciprocal pairing with IR node");
_SemanticModule->SetIrNode(nullptr);
}
else
{
ULANG_ASSERTF(_SemanticModule->GetAstNode() == this, "Expected reciprocal pairing with Ast node");
_SemanticModule->SetAstNode(nullptr);
}
}
}
//---------------------------------------------------------------------------------------
const CTypeBase* CExprModuleDefinition::GetResultType(const CSemanticProgram& Program) const
{
return &Program._voidType;
}
//=======================================================================================
// CExprEnumDefinition Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CExprEnumDefinition::CExprEnumDefinition(CEnumeration& Enum, TArray<TSRef<CExpressionBase>>&& Members, EVstMappingType VstMappingType)
: CExpressionBase(VstMappingType)
, _Enum(Enum)
, _Members(Move(Members))
{
if(IsIrNode())
{
ULANG_ASSERTF(_Enum.GetIrNode(true) == nullptr, "Expected reciprocal pairing with IR node");
_Enum.SetIrNode(this);
}
else
{
ULANG_ASSERTF(_Enum.GetAstNode() == nullptr, "Expected reciprocal pairing with AST node");
_Enum.SetAstNode(this);
}
}
//---------------------------------------------------------------------------------------
CExprEnumDefinition::~CExprEnumDefinition()
{
if (IsIrNode())
{
ULANG_ASSERTF(_Enum.GetIrNode(true) == this, "Expected reciprocal pairing with IR node");
_Enum.SetIrNode(nullptr);
}
else
{
ULANG_ASSERTF(_Enum.GetAstNode() == this, "Expected reciprocal pairing with AST node");
_Enum.SetAstNode(nullptr);
}
}
//---------------------------------------------------------------------------------------
const CTypeBase* CExprEnumDefinition::GetResultType(const CSemanticProgram& Program) const
{
return &_Enum;
}
//---------------------------------------------------------------------------------------
void CExprEnumDefinition::VisitImmediates(SAstVisitor& Visitor) const
{
CExpressionBase::VisitImmediates(Visitor);
Visitor.VisitImmediate("Enum", _Enum);
}
//=======================================================================================
// CExprScopedAccessLevelDefinition Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CExprScopedAccessLevelDefinition::CExprScopedAccessLevelDefinition(TSRef<CScopedAccessLevelDefinition>& AccessLevelDefinition, EVstMappingType VstMappingType)
: CExpressionBase(VstMappingType)
, _AccessLevelDefinition(AccessLevelDefinition)
{
if (IsIrNode())
{
ULANG_ASSERTF(_AccessLevelDefinition->GetIrNode(true) == nullptr, "Expected reciprocal pairing with IR node");
_AccessLevelDefinition->SetIrNode(this);
}
else
{
ULANG_ASSERTF(_AccessLevelDefinition->GetAstNode() == nullptr, "Expected reciprocal pairing with AST node");
_AccessLevelDefinition->SetAstNode(this);
}
SetResultType(_AccessLevelDefinition->GetTypeType());
}
//---------------------------------------------------------------------------------------
CExprScopedAccessLevelDefinition::~CExprScopedAccessLevelDefinition()
{
if (IsIrNode())
{
ULANG_ASSERTF(_AccessLevelDefinition->GetIrNode(true) == this, "Expected reciprocal pairing with IR node");
_AccessLevelDefinition->SetIrNode(nullptr);
}
else
{
ULANG_ASSERTF(_AccessLevelDefinition->GetAstNode() == this, "Expected reciprocal pairing with AST node");
_AccessLevelDefinition->SetAstNode(nullptr);
}
}
//---------------------------------------------------------------------------------------
void CExprScopedAccessLevelDefinition::VisitImmediates(SAstVisitor& Visitor) const
{
CExpressionBase::VisitImmediates(Visitor);
Visitor.VisitImmediate("AccessLevel", _AccessLevelDefinition->AsCode());
}
//=======================================================================================
// CExprInterfaceDefinition Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CExprInterfaceDefinition::CExprInterfaceDefinition(CInterface& Interface, TArray<TSRef<CExpressionBase>>&& SuperInterfaces, TArray<TSRef<CExpressionBase>>&& Members, EVstMappingType VstMappingType)
: CExpressionBase(VstMappingType)
, CMemberDefinitions(Move(Members))
, _Interface(Interface)
, _SuperInterfaces(Move(SuperInterfaces))
{
if (IsIrNode())
{
ULANG_ASSERTF(_Interface.GetIrNode(true) == nullptr, "Expected reciprocal pairing with IR node");
_Interface.SetIrNode(this);
}
else
{
ULANG_ASSERTF(_Interface.GetAstNode() == nullptr, "Expected reciprocal pairing with AST node");
_Interface.SetAstNode(this);
}
SetResultType(&Interface.GetProgram().GetOrCreateTypeType(Interface._NegativeInterface, &Interface));
}
//---------------------------------------------------------------------------------------
CExprInterfaceDefinition::~CExprInterfaceDefinition()
{
if (IsIrNode())
{
ULANG_ASSERTF(_Interface.GetIrNode(true) == this, "Expected reciprocal pairing with IR node");
_Interface.SetIrNode(nullptr);
}
else
{
ULANG_ASSERTF(_Interface.GetAstNode() == this, "Expected reciprocal pairing with AST node");
_Interface.SetAstNode(nullptr);
}
}
//---------------------------------------------------------------------------------------
void CExprInterfaceDefinition::VisitImmediates(SAstVisitor& Visitor) const
{
CExpressionBase::VisitImmediates(Visitor);
Visitor.VisitImmediate("Interface", _Interface);
}
//=======================================================================================
// CExprClassDefinition Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CExprClassDefinition::CExprClassDefinition(CClass& Class, TArray<TSRef<CExpressionBase>>&& SuperTypes, TArray<TSRef<CExpressionBase>>&& Members, EVstMappingType VstMappingType)
: CExpressionBase(VstMappingType)
, CMemberDefinitions(Move(Members))
, _Class(Class)
, _SuperTypes(Move(SuperTypes))
{
if (IsIrNode())
{
ULANG_ASSERTF(_Class._Definition->GetIrNode(true) == nullptr, "Expected reciprocal pairing with IR node");
_Class._Definition->SetIrNode(this);
}
else
{
ULANG_ASSERTF(_Class._Definition->GetAstNode() == nullptr, "Expected reciprocal pairing with AST node");
_Class._Definition->SetAstNode(this);
}
SetResultType(&Class.GetProgram().GetOrCreateTypeType(Class._NegativeClass, &Class));
}
//---------------------------------------------------------------------------------------
CExprClassDefinition::~CExprClassDefinition()
{
if (IsIrNode())
{
ULANG_ASSERTF(_Class._Definition->GetIrNode(true) == this, "Expected reciprocal pairing with IR node");
_Class._Definition->SetIrNode(nullptr);
}
else
{
ULANG_ASSERTF(_Class._Definition->GetAstNode() == this, "Expected reciprocal pairing with AST node");
_Class._Definition->SetAstNode(nullptr);
}
}
//---------------------------------------------------------------------------------------
void CExprClassDefinition::VisitImmediates(SAstVisitor& Visitor) const
{
CExpressionBase::VisitImmediates(Visitor);
Visitor.VisitImmediate("Class", *_Class.Definition());
if (CClass* Super = _Class._Superclass)
{
Visitor.VisitImmediate("Superclass", *Super->Definition());
}
}
//=======================================================================================
// CExprDataDefinition Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CExprDataDefinition::CExprDataDefinition(const TSRef<CDataDefinition>& DataMember, TSPtr<CExpressionBase>&& Element, TSPtr<CExpressionBase>&& ValueDomain, TSPtr<CExpressionBase>&& Value, EVstMappingType VstMappingType)
: CExprDefinition(Move(Element), Move(ValueDomain), Move(Value), VstMappingType)
, _DataMember(DataMember)
{
if (IsIrNode())
{
ULANG_ASSERTF(_DataMember->GetIrNode(true) == nullptr, "Expected reciprocal pairing with IR node");
_DataMember->SetIrNode(this);
}
else
{
ULANG_ASSERTF(_DataMember->GetAstNode() == nullptr, "Expected reciprocal pairing with AST node");
_DataMember->SetAstNode(this);
}
}
//---------------------------------------------------------------------------------------
CExprDataDefinition::~CExprDataDefinition()
{
if (IsIrNode())
{
ULANG_ASSERTF(_DataMember->GetIrNode(true) == this, "Expected reciprocal pairing with IR node");
_DataMember->SetIrNode(nullptr);
}
else
{
ULANG_ASSERTF(_DataMember->GetAstNode() == this, "Expected reciprocal pairing with AST node");
_DataMember->SetAstNode(nullptr);
}
}
//---------------------------------------------------------------------------------------
const CTypeBase* CExprDataDefinition::GetResultType(const CSemanticProgram& Program) const
{
// If the result type is explicitly set, use it. This is required for `var`
// definition expressions, which are of pointer type but evaluate to the
// contained value.
if (const CTypeBase* ResultType = CExprDefinition::GetResultType(Program))
{
return ResultType;
}
// Otherwise, use the related data member type.
if (_DataMember->GetType() == nullptr)
{
return Program.GetDefaultUnknownType();
}
else
{
return _DataMember->GetType();
}
}
//=======================================================================================
// CExprIterationPairDefinition Methods
//=======================================================================================
CExprIterationPairDefinition::CExprIterationPairDefinition(
TSRef<CDataDefinition>&& KeyDefinition,
TSRef<CDataDefinition>&& ValueDefinition,
TSPtr<CExpressionBase>&& Element,
TSPtr<CExpressionBase>&& ValueDomain,
TSPtr<CExpressionBase>&& Value,
EVstMappingType VstMappingType /* = EVstMappingType::Ast */)
: CExprDefinition(Move(Element), Move(ValueDomain), Move(Value), VstMappingType)
, _KeyDefinition(Move(KeyDefinition))
, _ValueDefinition(Move(ValueDefinition))
{
if (IsIrNode())
{
ULANG_ASSERTF(_KeyDefinition->GetIrNode(true) == nullptr, "Expected reciprocal pairing with IR node");
_KeyDefinition->SetIrNode(this);
ULANG_ASSERTF(_ValueDefinition->GetIrNode(true) == nullptr, "Expected reciprocal pairing with IR node");
_ValueDefinition->SetIrNode(this);
}
else
{
ULANG_ASSERTF(_KeyDefinition->GetAstNode() == nullptr, "Expected reciprocal pairing with AST node");
_KeyDefinition->SetAstNode(this);
ULANG_ASSERTF(_ValueDefinition->GetAstNode() == nullptr, "Expected reciprocal pairing with AST node");
_ValueDefinition->SetAstNode(this);
}
}
CExprIterationPairDefinition::~CExprIterationPairDefinition()
{
if (IsIrNode())
{
ULANG_ASSERTF(_KeyDefinition->GetIrNode(true) == this, "Expected reciprocal pairing with IR node");
_KeyDefinition->SetIrNode(nullptr);
ULANG_ASSERTF(_ValueDefinition->GetIrNode(true) == this, "Expected reciprocal pairing with IR node");
_ValueDefinition->SetIrNode(nullptr);
}
else
{
ULANG_ASSERTF(_KeyDefinition->GetAstNode() == this, "Expected reciprocal pairing with AST node");
_KeyDefinition->SetAstNode(nullptr);
ULANG_ASSERTF(_ValueDefinition->GetAstNode() == this, "Expected reciprocal pairing with AST node");
_ValueDefinition->SetAstNode(nullptr);
}
}
//=======================================================================================
// CExprFunctionDefinition Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CExprFunctionDefinition::CExprFunctionDefinition(const TSRef<CFunction>& Function, TSPtr<CExpressionBase>&& Element, TSPtr<CExpressionBase>&& ValueDomain, TSPtr<CExpressionBase>&& Value, EVstMappingType VstMappingType)
: CExprDefinition(Move(Element), Move(ValueDomain), Move(Value), VstMappingType)
, _Function(Function)
{
if (IsIrNode())
{
ULANG_ASSERTF(_Function->GetIrNode(true) == nullptr, "Expected reciprocal pairing with IR node");
_Function->SetIrNode(this);
}
else
{
ULANG_ASSERTF(_Function->GetAstNode() == nullptr, "Expected reciprocal pairing with AST node");
_Function->SetAstNode(this);
}
}
//---------------------------------------------------------------------------------------
CExprFunctionDefinition::~CExprFunctionDefinition()
{
if (IsIrNode())
{
ULANG_ASSERTF(_Function->GetIrNode(true) == this, "Expected reciprocal pairing with IR node");
_Function->SetIrNode(nullptr);
}
else
{
ULANG_ASSERTF(_Function->GetAstNode() == this, "Expected reciprocal pairing with AST node");
_Function->SetAstNode(nullptr);
}
}
//---------------------------------------------------------------------------------------
const CTypeBase* CExprFunctionDefinition::GetResultType(const CSemanticProgram& Program) const
{
return _Function->_Signature.GetFunctionType();
}
//---------------------------------------------------------------------------------------
bool CExprFunctionDefinition::HasUserAddedPredictsEffect(const CSemanticProgram& Program) const
{
return Element() && Element()->HasAttributeClass(Program._predictsClass, Program);
}
//=======================================================================================
// CExprTypeAliasDefinition Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
CExprTypeAliasDefinition::CExprTypeAliasDefinition(const TSRef<CTypeAlias>& TypeAlias, TSPtr<CExpressionBase>&& Element, TSPtr<CExpressionBase>&& ValueDomain, TSPtr<CExpressionBase>&& Value, EVstMappingType VstMappingType)
: CExprDefinition(Move(Element), Move(ValueDomain), Move(Value), VstMappingType)
, _TypeAlias(TypeAlias)
{
if (IsIrNode())
{
ULANG_ASSERTF(_TypeAlias->GetIrNode(true) == nullptr, "Expected reciprocal pairing with IR node");
_TypeAlias->SetIrNode(this);
}
else
{
ULANG_ASSERTF(_TypeAlias->GetAstNode() == nullptr, "Expected reciprocal pairing with AST node");
_TypeAlias->SetAstNode(this);
}
}
//---------------------------------------------------------------------------------------`
CExprTypeAliasDefinition::~CExprTypeAliasDefinition()
{
if (IsIrNode())
{
ULANG_ASSERTF(_TypeAlias->GetIrNode(true) == this, "Expected reciprocal pairing with IR node");
_TypeAlias->SetIrNode(nullptr);
}
else
{
ULANG_ASSERTF(_TypeAlias->GetAstNode() == this, "Expected reciprocal pairing with AST node");
_TypeAlias->SetAstNode(nullptr);
}
}
//=======================================================================================
// CExprUsing Methods
//=======================================================================================
const CTypeBase* CExprUsing::GetResultType(const CSemanticProgram& Program) const
{
return &Program._voidType;
}
void CExprUsing::VisitImmediates(SAstVisitor& Visitor) const
{
CExpressionBase::VisitImmediates(Visitor);
if (_Module)
{
Visitor.VisitImmediate("Module", *_Module);
}
}
//=======================================================================================
// CExprImport Methods
//=======================================================================================
CExprImport::CExprImport(const TSRef<CModuleAlias>& ModuleAlias, TSRef<CExpressionBase>&& Path, EVstMappingType VstMappingType)
: CExpressionBase(VstMappingType)
, _ModuleAlias(ModuleAlias)
, _Path(Move(Path))
{
if (IsIrNode())
{
ULANG_ASSERTF(_ModuleAlias->GetIrNode(true) == nullptr, "Expected reciprocal pairing with IR node");
_ModuleAlias->SetIrNode(this);
}
else
{
ULANG_ASSERTF(_ModuleAlias->GetAstNode() == nullptr, "Expected reciprocal pairing with AST node");
_ModuleAlias->SetAstNode(this);
}
}
CExprImport::~CExprImport()
{
if (IsIrNode())
{
ULANG_ASSERTF(_ModuleAlias->GetIrNode(true) == this, "Expected reciprocal pairing with IR node");
_ModuleAlias->SetIrNode(nullptr);
}
else
{
ULANG_ASSERTF(_ModuleAlias->GetAstNode() == this, "Expected reciprocal pairing with AST node");
_ModuleAlias->SetAstNode(nullptr);
}
}
const CTypeBase* CExprImport::GetResultType(const CSemanticProgram& Program) const
{
return Program._typeType;
}
void CExprImport::VisitImmediates(SAstVisitor& Visitor) const
{
CExpressionBase::VisitImmediates(Visitor);
if (_ModuleAlias)
{
Visitor.VisitImmediate("ModuleAlias", *_ModuleAlias);
}
}
//=======================================================================================
// CExprVar Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
bool CExprVar::operator==(const CExpressionBase& Other) const
{
if (Other.GetNodeType() != EAstNodeType::Definition_Var)
{
return false;
}
const CExprVar& OtherVar = static_cast<const CExprVar&>(Other);
if (_bIsLive != OtherVar._bIsLive)
{
return false;
}
if (!IsSubExprEqual(Operand(), OtherVar.Operand()))
{
return false;
}
return true;
}
//=======================================================================================
// CExprLive Methods
//=======================================================================================
//---------------------------------------------------------------------------------------
bool CExprLive::operator==(const CExpressionBase& Other) const
{
if (Other.GetNodeType() != EAstNodeType::Definition_Live)
{
return false;
}
const CExprLive& OtherVar = static_cast<const CExprLive&>(Other);
if (!IsSubExprEqual(Operand(), OtherVar.Operand()))
{
return false;
}
return true;
}
//=======================================================================================
// CAstPackage Methods
//=======================================================================================
void CAstPackage::VisitImmediates(SAstVisitor& Visitor) const
{
CAstNode::VisitImmediates(Visitor);
Visitor.VisitImmediate("Name", _Name);
Visitor.VisitImmediate("VersePath", _VersePath);
if (_RootModule)
{
Visitor.VisitImmediate("RootModule", _RootModule->GetModule());
}
Visitor.BeginArray("Dependencies", _Dependencies.Num());
for (const CAstPackage* Dependency : _Dependencies)
{
Visitor.VisitImmediate("", Dependency->_Name);
}
Visitor.EndArray();
Visitor.VisitImmediate("Scope", ToString(_VerseScope));
Visitor.VisitImmediate("Role", ToString(_Role));
Visitor.VisitImmediate("EffectiveVerseVersion", static_cast<int64_t>(_EffectiveVerseVersion));
Visitor.VisitImmediate("UploadedAtFNVersion", static_cast<int64_t>(_UploadedAtFNVersion));
Visitor.VisitImmediate("bAllowNative", _bAllowNative);
Visitor.VisitImmediate("bTreatModulesAsImplicit", _bTreatModulesAsImplicit);
Visitor.VisitImmediate("AllowExperimental", _bAllowExperimental);
}
bool CAstPackage::CanSeeDefinition(const CDefinition& Definition) const
{
if (Definition.IsBuiltIn())
{
return true;
}
else if (const CModule* Module = Definition.AsNullable<CModule>())
{
for (const CModulePart* Part : Module->GetParts())
{
const CAstPackage* DefinitionPackage = Part->GetPackage();
if (!DefinitionPackage || DefinitionPackage == this || _Dependencies.Contains(DefinitionPackage))
{
return true;
}
}
return false;
}
else
{
const CAstPackage* DefinitionPackage = Definition._EnclosingScope.GetPackage();
return !DefinitionPackage || DefinitionPackage == this || _Dependencies.Contains(DefinitionPackage);
}
}
//=======================================================================================
// CAstCompilationUnit Methods
//=======================================================================================
EPackageRole CAstCompilationUnit::GetRole() const
{
ULANG_ASSERT(!_Packages.IsEmpty());
EPackageRole Role = _Packages[0]->_Role;
#if ULANG_DO_CHECK
// Validate assumption that all packages have the same role
for (int32_t Index = 1; Index < _Packages.Num(); ++Index)
{
ULANG_ASSERT(_Packages[Index]->_Role == Role);
}
#endif
return Role;
}
bool CAstCompilationUnit::IsAllowNative() const
{
#if ULANG_DO_CHECK
if (_Packages.Num() > 1)
{
// Validate assumption that all packages with mutual dependencies must be non-native
for (int32_t Index = 0; Index < _Packages.Num(); ++Index)
{
ULANG_ASSERTF(!_Packages[Index]->_bAllowNative, "Cicular dependencies with a native package are not supported. Native package found: %s", _Packages[Index]->_Name.AsCString());
}
}
#endif
return _Packages.Num() == 1 && _Packages[0]->_bAllowNative;
}
//=======================================================================================
// CAstProject Methods
//=======================================================================================
const CAstPackage* CAstProject::FindPackageByName(const CUTF8String& PackageName) const
{
for (const CAstCompilationUnit* CompilationUnit : _OrderedCompilationUnits)
{
for (const CAstPackage* Package : CompilationUnit->Packages())
{
if (Package->_Name == PackageName)
{
return Package;
}
}
}
return nullptr;
}
int32_t CAstProject::GetNumPackages() const
{
int32_t NumPackages = 0;
for (const CAstCompilationUnit* CompilationUnit : _OrderedCompilationUnits)
{
NumPackages += CompilationUnit->Packages().Num();
}
return NumPackages;
}
TOptional<SAssignmentLhsIdentifier> IdentifierOfAssignmentLhs(const CExprAssignment* Assignment)
{
if (!Assignment)
{
return {};
}
auto SetExpr = AsNullable<CExprSet>(Assignment->Lhs());
if (!SetExpr) { return {}; }
auto PtrToRef = AsNullable<CExprPointerToReference>(SetExpr->Operand());
if (!PtrToRef) { return {}; }
auto IdentifierData = AsNullable<CExprIdentifierData>(PtrToRef->Operand());
if (!IdentifierData) { return {}; }
return {{PtrToRef, IdentifierData}};
}
bool HasImplicitClassSelf(const CExprIdentifierData* Expr)
{
if (!Expr)
{
return false;
}
const CScope& Scope = Expr->_DataDefinition._EnclosingScope.GetLogicalScope();
return !Expr->Context()
&& Scope.GetKind() == CScope::EKind::Class
&& static_cast<const CClassDefinition&>(Scope)._StructOrClass == EStructOrClass::Class;
}
bool IsClassMemberAccess(const CExprIdentifierData* Expr)
{
return Expr && (Expr->Context() || HasImplicitClassSelf(Expr));
}
const CExprInvocation* AsSubscriptCall(const CExpressionBase* Expr, const CSemanticProgram& Program)
{
if (auto Invocation = AsNullable<CExprInvocation>(Expr))
{
if (auto Callee = AsNullable<CExprIdentifierFunction>(Invocation->GetCallee()))
{
if (Callee->_Function.GetName() == Program._IntrinsicSymbols._OpNameCall
&& Callee->_Function._Signature.NumParams() == 2)
{
auto& ReferenceValueType =
Callee->_Function._Signature.GetParamType(0)->GetNormalType().GetReferenceValueType()->GetNormalType();
if (ReferenceValueType.IsA<CArrayType>() || ReferenceValueType.IsA<CMapType>())
{
return Invocation;
}
}
}
}
return nullptr;
}
const CExpressionBase* RemoveSubscripts(const CExpressionBase* Expr, const CSemanticProgram& Program)
{
const CExpressionBase* It = Expr;
while (true)
{
const CExprInvocation* Call = AsSubscriptCall(It, Program);
if (!Call)
{
break;
}
auto Args = AsNullable<CExprMakeTuple>(Call->GetArgument());
ULANG_ASSERT(Args && !Args->IsEmpty());
It = Args->GetSubExprs()[0];
}
return It;
}
} // namespace uLang