Files
UnrealEngine/Engine/Source/Developer/ShaderCompilerCommon/Private/HlslAST.cpp
2025-05-18 13:04:45 +08:00

1627 lines
32 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
HlslAST.cpp - Abstract Syntax Tree implementation for HLSL.
=============================================================================*/
#include "HlslAST.h"
namespace CrossCompiler
{
namespace AST
{
static void WriteOptionArraySize(FASTWriter& Writer, bool bIsArray, const TLinearArray<FExpression*>& ArraySize)
{
if (bIsArray && ArraySize.Num() == 0)
{
Writer << TEXT("[]");
}
else
{
for (const auto* Dimension : ArraySize)
{
Writer << (TCHAR)'[';
if (Dimension)
{
Dimension->Write(Writer);
}
Writer << (TCHAR)']';
}
}
}
#if 0
FNode::FNode()/* :
Prev(nullptr),
Next(nullptr)*/
{
}
#endif // 0
FNode::FNode(FLinearAllocator* Allocator, const FSourceInfo& InInfo) :
SourceInfo(InInfo),
Attributes(Allocator)/*,
Prev(nullptr),
Next(nullptr)*/
{
}
void FASTWriter::DoIndent()
{
int32 N = Indent;
while (--N >= 0)
{
(*this) << (TCHAR)'\t';
}
}
void FNode::WriteAttributes(FASTWriter& Writer) const
{
if (Attributes.Num() > 0)
{
for (auto* Attr : Attributes)
{
Attr->Write(Writer);
}
Writer << (TCHAR)' ';
}
}
FPragma::FPragma(FLinearAllocator* InAllocator, const TCHAR* InPragma, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo)
{
Pragma = InAllocator->Strdup(InPragma);
}
void FPragma::Write(FASTWriter& Writer) const
{
Writer << Pragma << TEXT("\n");
}
FExpression::FExpression(FLinearAllocator* InAllocator, EOperators InOperator, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
Operator(InOperator),
Identifier(nullptr),
Expressions(InAllocator)
{
TypeSpecifier = nullptr;
}
FExpression::FExpression(FLinearAllocator* InAllocator, EOperators InOperator, FExpression* E0, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
Operator(InOperator),
Identifier(nullptr),
Expressions(InAllocator)
{
Expressions.SetNumUninitialized(1);
Expressions[0] = E0;
TypeSpecifier = nullptr;
}
FExpression::FExpression(FLinearAllocator* InAllocator, EOperators InOperator, FExpression* E0, FExpression* E1, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
Operator(InOperator),
Identifier(nullptr),
Expressions(InAllocator)
{
Expressions.SetNumUninitialized(2);
Expressions[0] = E0;
Expressions[1] = E1;
TypeSpecifier = nullptr;
}
FExpression::FExpression(FLinearAllocator* InAllocator, EOperators InOperator, FExpression* E0, FExpression* E1, FExpression* E2, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
Operator(InOperator),
Identifier(nullptr),
Expressions(InAllocator)
{
Expressions.SetNumUninitialized(3);
Expressions[0] = E0;
Expressions[1] = E1;
Expressions[2] = E2;
TypeSpecifier = nullptr;
}
void FExpression::WriteOperator(FASTWriter& Writer) const
{
switch (Operator)
{
case EOperators::Plus:
Writer << TEXT("+");
break;
case EOperators::Minus:
Writer << TEXT("-");
break;
case EOperators::Assign:
Writer << TEXT("=");
break;
case EOperators::AddAssign:
Writer << TEXT("+=");
break;
case EOperators::SubAssign:
Writer << TEXT("-=");
break;
case EOperators::MulAssign:
Writer << TEXT("*=");
break;
case EOperators::DivAssign:
Writer << TEXT("/=");
break;
case EOperators::ModAssign:
Writer << TEXT("%=");
break;
case EOperators::RSAssign:
Writer << TEXT(">>=");
break;
case EOperators::LSAssign:
Writer << TEXT("<<=");
break;
case EOperators::AndAssign:
Writer << TEXT("&=");
break;
case EOperators::OrAssign:
Writer << TEXT("|=");
break;
case EOperators::XorAssign:
Writer << TEXT("^=");
break;
case EOperators::Conditional:
Writer << TEXT("?");
break;
case EOperators::LogicOr:
Writer << TEXT("||");
break;
case EOperators::LogicAnd:
Writer << TEXT("&&");
break;
case EOperators::LogicNot:
Writer << TEXT("!");
break;
case EOperators::BitOr:
Writer << TEXT("|");
break;
case EOperators::BitXor:
Writer << TEXT("^");
break;
case EOperators::BitAnd:
Writer << TEXT("&");
break;
case EOperators::BitNeg:
Writer << TEXT("~");
break;
case EOperators::Equal:
Writer << TEXT("==");
break;
case EOperators::NEqual:
Writer << TEXT("!=");
break;
case EOperators::Less:
Writer << TEXT("<");
break;
case EOperators::Greater:
Writer << TEXT(">");
break;
case EOperators::LEqual:
Writer << TEXT("<=");
break;
case EOperators::GEqual:
Writer << TEXT(">=");
break;
case EOperators::LShift:
Writer << TEXT("<<");
break;
case EOperators::RShift:
Writer << TEXT(">>");
break;
case EOperators::Add:
Writer << TEXT("+");
break;
case EOperators::Sub:
Writer << TEXT("-");
break;
case EOperators::Mul:
Writer << TEXT("*");
break;
case EOperators::Div:
Writer << TEXT("/");
break;
case EOperators::Mod:
Writer << TEXT("%");
break;
case EOperators::PreInc:
Writer << TEXT("++");
break;
case EOperators::PreDec:
Writer << TEXT("--");
break;
case EOperators::PostInc:
case EOperators::PostDec:
case EOperators::FieldSelection:
case EOperators::ArrayIndex:
break;
case EOperators::TypeCast:
Writer << (TCHAR)'(';
TypeSpecifier->Write(Writer);
Writer << TEXT(")");
break;
default:
Writer << TEXT("*MISSING_");
Writer << (uint32)Operator;
Writer << (TCHAR)'*';
checkf(0, TEXT("Unhandled AST Operator %d!"), (uint32)Operator);
break;
}
}
void FExpression::Write(FASTWriter& Writer) const
{
switch (Operator)
{
case EOperators::Conditional:
Writer << (TCHAR)'(';
Expressions[0]->Write(Writer);
Writer << TEXT(" ? ");
Expressions[1]->Write(Writer);
Writer << TEXT(" : ");
Expressions[2]->Write(Writer);
Writer << TEXT(")");
break;
case EOperators::Literal:
Writer << Identifier;
break;
case EOperators::Identifier:
Writer << Identifier;
break;
default:
Writer << TEXT("*MISSING_");
Writer << (uint32)Operator;
Writer << (TCHAR)'*';
checkf(0, TEXT("Unhandled AST Operator %d!"), (int32)Operator);
break;
}
}
bool FExpression::GetConstantIntValue(int32& OutValue) const
{
if (IsConstant())
{
checkf(Identifier!=nullptr, TEXT("Null identifier, literaltype %d"), (int32)LiteralType);
OutValue = (int32)FCString::Atoi(Identifier->GetData());
return true;
}
return false;
}
FExpression::~FExpression()
{
for (auto* Expr : Expressions)
{
if (Expr)
{
delete Expr;
}
}
for (int32 Index = 0; Index < Expressions.Num(); ++Index)
{
if (Expressions[Index])
{
delete Expressions[Index];
}
else
{
break;
}
}
}
FUnaryExpression::FUnaryExpression(FLinearAllocator* InAllocator, EOperators InOperator, FExpression* Expr, const FSourceInfo& InInfo) :
FExpression(InAllocator, InOperator, Expr, InInfo)
{
}
void FUnaryExpression::Write(FASTWriter& Writer) const
{
WriteOperator(Writer);
if (Writer.ExpressionScope != 0 && Operator != EOperators::FieldSelection)
{
Writer << (TCHAR)'(';
}
if (Expressions.Num() != 0)
{
++Writer.ExpressionScope;
Expressions[0]->Write(Writer);
--Writer.ExpressionScope;
}
// Suffix
switch (Operator)
{
case EOperators::PostInc:
Writer << TEXT("++");
break;
case EOperators::PostDec:
Writer << TEXT("--");
break;
case EOperators::FieldSelection:
Writer << (TCHAR)'.';
Writer << Identifier;
break;
default:
break;
}
if (Writer.ExpressionScope != 0 && Operator != EOperators::FieldSelection)
{
Writer << (TCHAR)')';
}
}
FBinaryExpression::FBinaryExpression(FLinearAllocator* InAllocator, EOperators InOperator, FExpression* E0, FExpression* E1, const FSourceInfo& InInfo) :
FExpression(InAllocator, InOperator, E0, E1, InInfo)
{
}
void FBinaryExpression::Write(FASTWriter& Writer) const
{
switch (Operator)
{
case EOperators::ArrayIndex:
if (Expressions[0]->AsUnaryExpression() && Expressions[0]->Operator == EOperators::Identifier)
{
Expressions[0]->Write(Writer);
}
else
{
Writer << (TCHAR)'(';
Expressions[0]->Write(Writer);
Writer << (TCHAR)')';
}
Writer << (TCHAR)'[';
Expressions[1]->Write(Writer);
Writer << (TCHAR)']';
break;
default:
if (Writer.ExpressionScope != 0 && !IsAssignmentOperator(Operator))
{
Writer << (TCHAR)'(';
}
++Writer.ExpressionScope;
Expressions[0]->Write(Writer);
Writer << (TCHAR)' ';
WriteOperator(Writer);
Writer << (TCHAR)' ';
Expressions[1]->Write(Writer);
--Writer.ExpressionScope;
if (Writer.ExpressionScope != 0 && !IsAssignmentOperator(Operator))
{
Writer << (TCHAR)')';
}
break;
}
}
bool FBinaryExpression::GetConstantIntValue(int32& OutValue) const
{
int32 LHS = 0;
int32 RHS = 0;
if (!Expressions[0]->GetConstantIntValue(LHS) || !Expressions[1]->GetConstantIntValue(RHS))
{
return false;
}
switch (Operator)
{
default:
return false;
case EOperators::LogicOr: OutValue = LHS || RHS; break;
case EOperators::LogicAnd: OutValue = LHS && RHS; break;
case EOperators::BitOr: OutValue = LHS | RHS; break;
case EOperators::BitXor: OutValue = LHS ^ RHS; break;
case EOperators::BitAnd: OutValue = LHS ^ RHS; break;
case EOperators::Equal: OutValue = LHS == RHS; break;
case EOperators::NEqual: OutValue = LHS != RHS; break;
case EOperators::Less: OutValue = LHS < RHS; break;
case EOperators::Greater: OutValue = LHS > RHS; break;
case EOperators::LEqual: OutValue = LHS <= RHS; break;
case EOperators::GEqual: OutValue = LHS >= RHS; break;
case EOperators::LShift: OutValue = LHS << RHS; break;
case EOperators::RShift: OutValue = LHS >> RHS; break;
case EOperators::Add: OutValue = LHS + RHS; break;
case EOperators::Sub: OutValue = LHS - RHS; break;
case EOperators::Mul: OutValue = LHS * RHS; break;
case EOperators::Div: OutValue = LHS / RHS; break;
case EOperators::Mod: OutValue = LHS % RHS; break;
}
return true;
}
FExpressionStatement::FExpressionStatement(FLinearAllocator* InAllocator, FExpression* InExpr, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
Expression(InExpr)
{
}
void FExpressionStatement::Write(FASTWriter& Writer) const
{
Writer.DoIndent();
Expression->Write(Writer);
Writer << TEXT(";\n");
}
FExpressionStatement::~FExpressionStatement()
{
if (Expression)
{
delete Expression;
}
}
FCompoundStatement::FCompoundStatement(FLinearAllocator* InAllocator, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
Statements(InAllocator)
{
}
void FCompoundStatement::Write(FASTWriter& Writer) const
{
Writer.DoIndent();
Writer << TEXT("{\n");
for (auto* Statement : Statements)
{
FASTWriterIncrementScope Scope(Writer);
Statement->Write(Writer);
}
Writer.DoIndent();
Writer << TEXT("}\n");
}
FCompoundStatement::~FCompoundStatement()
{
for (auto* Statement : Statements)
{
delete Statement;
}
}
FStaticAssertStatement::FStaticAssertStatement(FLinearAllocator* InAllocator, const FSourceInfo& InInfo, const FString& InKeyword) :
FNode(InAllocator, InInfo),
Keyword(InKeyword),
Condition(nullptr)
{
}
FStaticAssertStatement::~FStaticAssertStatement()
{
delete Condition;
}
void FStaticAssertStatement::Write(FASTWriter& Writer) const
{
Writer.DoIndent();
Writer << *Keyword << TEXT("(");
checkf(Condition != nullptr, TEXT("Cannot write %s()-statement in HLSL without a conditional expression"), *Keyword);
Condition->Write(Writer);
Writer << TEXT(", \"") << *Message << TEXT("\");\n");
}
FC99PragmaStatement::FC99PragmaStatement(FLinearAllocator* InAllocator, const FSourceInfo& InInfo, const FString& InArgument) :
FNode(InAllocator, InInfo),
Argument(InArgument)
{
}
FC99PragmaStatement::~FC99PragmaStatement()
{
}
void FC99PragmaStatement::Write(FASTWriter& Writer) const
{
Writer << TEXT("_Pragma(\"") << *Argument << TEXT("\")\n");
}
FFunctionDefinition::FFunctionDefinition(FLinearAllocator* InAllocator, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
Prototype(nullptr),
Body(nullptr)
{
}
void FFunctionDefinition::Write(FASTWriter& Writer) const
{
WriteAttributes(Writer);
Prototype->Write(Writer);
if (Body)
{
Body->Write(Writer);
}
}
FFunctionDefinition::~FFunctionDefinition()
{
delete Prototype;
delete Body;
}
FFunction::FFunction(FLinearAllocator* InAllocator, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
ReturnType(nullptr),
ScopeIdentifier(nullptr),
Identifier(nullptr),
ReturnSemantic(nullptr),
Parameters(InAllocator),
bIsDefinition(false),
bIsOperator(false),
bIsStatic(false)
{
}
void FFunction::Write(FASTWriter& Writer) const
{
WriteAttributes(Writer);
Writer << TEXT("\n");
if (bIsStatic)
{
Writer << TEXT("static ");
}
ReturnType->Write(Writer);
Writer << (TCHAR)' ';
if (ScopeIdentifier)
{
Writer << ScopeIdentifier << TEXT("::");
}
if (bIsOperator)
{
Writer << TEXT("operator");
}
Writer << Identifier;
Writer << (TCHAR)'(';
bool bFirst = true;
const int32 ParamsPerLine = 6;
for (int32 Index = 0; Index < Parameters.Num(); ++Index)
{
if (Index > 0)
{
if ((Index % ParamsPerLine) == 0)
{
Writer << TEXT(",\n\t\t");
}
else
{
Writer << TEXT(", ");
}
}
Parameters[Index]->Write(Writer);
}
Writer << TEXT(")");
if (ReturnSemantic)
{
ReturnSemantic->Write(Writer);
}
if (bIsDefinition)
{
Writer << TEXT(";\n");
}
else
{
Writer << TEXT("\n");
}
}
FFunction::~FFunction()
{
for (auto* Param : Parameters)
{
delete Param;
}
}
FJumpStatement::FJumpStatement(FLinearAllocator* InAllocator, EJumpType InType, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
Type(InType),
OptionalExpression(nullptr)
{
}
void FJumpStatement::Write(FASTWriter& Writer) const
{
Writer.DoIndent();
switch (Type)
{
case EJumpType::Return:
Writer << TEXT("return");
break;
case EJumpType::Break:
Writer << TEXT("break");
break;
case EJumpType::Continue:
Writer << TEXT("continue");
break;
default:
Writer << TEXT("*MISSING_");
Writer << (uint32)Type;
Writer << (TCHAR)'*';
checkf(0, TEXT("Unhandled AST jump type %d!"), (int32)Type);
break;
}
if (OptionalExpression)
{
Writer << TEXT(" ");
OptionalExpression->Write(Writer);
}
Writer << TEXT(";\n");
}
FJumpStatement::~FJumpStatement()
{
if (OptionalExpression)
{
delete OptionalExpression;
}
}
FSelectionStatement::FSelectionStatement(FLinearAllocator* InAllocator, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
Condition(nullptr),
ThenStatement(nullptr),
ElseStatement(nullptr)
{
}
void FSelectionStatement::Write(FASTWriter& Writer) const
{
Writer.DoIndent();
WriteAttributes(Writer);
Writer << TEXT("if (");
Condition->Write(Writer);
Writer << TEXT(")\n");
ThenStatement->Write(Writer);
if (ElseStatement)
{
Writer.DoIndent();
Writer << TEXT("else\n");
ElseStatement->Write(Writer);
}
}
FSelectionStatement::~FSelectionStatement()
{
delete Condition;
delete ThenStatement;
if (ElseStatement)
{
delete ElseStatement;
}
}
FTypeSpecifier::FTypeSpecifier(FLinearAllocator* InAllocator, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
TypeName(nullptr),
InnerType(nullptr),
Structure(nullptr),
TextureMSNumSamples(1),
PatchSize(0),
bIsArray(false),
//bIsUnsizedArray(false),
ArraySize(nullptr)
{
}
void FTypeSpecifier::Write(FASTWriter& Writer) const
{
if (Structure)
{
Structure->Write(Writer);
}
else
{
if (bPrecise)
{
Writer << TEXT("precise ");
}
Writer << TypeName;
if (TextureMSNumSamples > 1)
{
Writer << (TCHAR)'<';
Writer << InnerType;
Writer << TEXT(", ");
Writer << (uint32)TextureMSNumSamples;
Writer << (TCHAR)'>';
}
else if (InnerType && *InnerType)
{
Writer << (TCHAR)'<';
Writer << InnerType;
Writer << (TCHAR)'>';
}
}
if (bIsArray)
{
Writer << TEXT("[ ");
if (ArraySize)
{
ArraySize->Write(Writer);
}
printf("]");
}
}
FTypeSpecifier::~FTypeSpecifier()
{
if (Structure)
{
delete Structure;
}
if (ArraySize)
{
delete ArraySize;
}
}
FCBufferDeclaration::FCBufferDeclaration(FLinearAllocator* InAllocator, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
Name(nullptr),
Declarations(InAllocator)
{
}
void FCBufferDeclaration::Write(FASTWriter& Writer) const
{
Writer.DoIndent();
Writer << TEXT("cbuffer ");
Writer << Name;
Writer << (TCHAR)'\n';
Writer.DoIndent();
Writer << TEXT("{\n");
for (auto* Declaration : Declarations)
{
FASTWriterIncrementScope Scope(Writer);
Declaration->Write(Writer);
}
Writer.DoIndent();
Writer << TEXT("}\n\n");
}
FCBufferDeclaration::~FCBufferDeclaration()
{
for (auto* Decl : Declarations)
{
delete Decl;
}
}
FTypeQualifier::FTypeQualifier()
{
Raw = 0;
}
void FTypeQualifier::Write(FASTWriter& Writer) const
{
if (bIsStatic)
{
Writer << TEXT("static ");
}
if (bConstant)
{
Writer << TEXT("const ");
}
if (bShared)
{
Writer << TEXT("groupshared ");
}
else if (bIn && bOut)
{
Writer << TEXT("inout ");
}
else if (bIn)
{
Writer << TEXT("in ");
}
else if (bOut)
{
Writer << TEXT("out ");
}
if (bLinear)
{
Writer << TEXT("linear ");
}
if (bCentroid)
{
Writer << TEXT("centroid ");
}
if (NoInterpolatorType)
{
Writer << NoInterpolatorType;
Writer << (TCHAR)' ';
}
if (NoPerspectiveType)
{
Writer << NoPerspectiveType;
Writer << (TCHAR)' ';
}
if (bSample)
{
Writer << TEXT("sample ");
}
if (bRowMajor)
{
Writer << TEXT("row_major ");
}
if (PrimitiveType)
{
Writer << PrimitiveType;
Writer << (TCHAR)' ';
}
}
FFullySpecifiedType::FFullySpecifiedType(FLinearAllocator* InAllocator, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
Specifier(nullptr)
{
}
void FFullySpecifiedType::Write(FASTWriter& Writer) const
{
Qualifier.Write(Writer);
Specifier->Write(Writer);
}
FFullySpecifiedType::~FFullySpecifiedType()
{
delete Specifier;
}
FSemanticSpecifier::FSemanticSpecifier(FLinearAllocator* InAllocator, FSemanticSpecifier::ESpecType InType, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
Arguments(InAllocator),
Type(InType),
Semantic(nullptr)
{
}
FSemanticSpecifier::FSemanticSpecifier(FLinearAllocator* InAllocator, const TCHAR* InSemantic, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
Arguments(InAllocator),
Type(FSemanticSpecifier::ESpecType::Semantic)
{
Semantic = InAllocator->Strdup(InSemantic);
}
FSemanticSpecifier::~FSemanticSpecifier()
{
for (FExpression* Expr : Arguments)
{
delete Expr;
}
}
void FSemanticSpecifier::Write(FASTWriter& Writer) const
{
Writer << TEXT(" : ");
switch (Type)
{
case ESpecType::Semantic:
Writer << Semantic;
Writer << TEXT(" ");
break;
case ESpecType::Register:
Writer << TEXT("register");
break;
case ESpecType::PackOffset:
Writer << TEXT("packoffset");
break;
default:
Writer << *FString::Printf(TEXT("<Unknown Type value %d!>"), (int32)Type);
}
if (Arguments.Num() > 0)
{
Writer << TEXT("(");
for (int32 Index = 0, Num = Arguments.Num(); Index < Num; ++Index)
{
Arguments[Index]->Write(Writer);
if (Index + 1 < Num)
{
Writer << TEXT(", ");
}
}
Writer << TEXT(")");
}
}
FDeclaration::FDeclaration(FLinearAllocator* InAllocator, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
Identifier(nullptr),
Semantic(nullptr),
bIsArray(false),
ArraySize(InAllocator),
Initializer(nullptr)
{
}
void FDeclaration::Write(FASTWriter& Writer) const
{
WriteAttributes(Writer);
Writer << Identifier;
WriteOptionArraySize(Writer, bIsArray, ArraySize);
if (Initializer)
{
Writer << TEXT(" = ");
Initializer->Write(Writer);
}
if (Semantic)
{
Semantic->Write(Writer);
}
}
FDeclaration::~FDeclaration()
{
for (auto* Expr : ArraySize)
{
delete Expr;
}
if (Initializer)
{
delete Initializer;
}
}
FDeclaratorList::FDeclaratorList(FLinearAllocator* InAllocator, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
Type(nullptr),
Declarations(InAllocator)
{
}
void FDeclaratorList::WriteNoEOL(FASTWriter& Writer) const
{
WriteAttributes(Writer);
if (bTypedef)
{
Writer << TEXT("typedef ");
}
if (Type)
{
Type->Write(Writer);
Writer << TEXT(" ");
}
bool bFirst = true;
for (auto* Decl : Declarations)
{
if (bFirst)
{
bFirst = false;
}
else
{
Writer << TEXT(", ");
}
Decl->Write(Writer);
}
Writer << TEXT(";");
}
void FDeclaratorList::Write(FASTWriter& Writer) const
{
Writer.DoIndent();
WriteNoEOL(Writer);
Writer << TEXT("\n");
}
FDeclaratorList::~FDeclaratorList()
{
delete Type;
for (auto* Decl : Declarations)
{
delete Decl;
}
}
FExpressionList::FExpressionList(FLinearAllocator* InAllocator, FExpressionList::EType InType, const FSourceInfo& InInfo) :
FExpression(InAllocator, EOperators::ExpressionList, InInfo),
Type(InType)
{
}
void FExpressionList::Write(FASTWriter& Writer) const
{
switch (Type)
{
case EType::Braced: Writer << TEXT("{"); break;
case EType::Parenthesized: Writer << TEXT("("); break;
default: break;
}
bool bFirst = true;
for (auto* Expr : Expressions)
{
if (bFirst)
{
bFirst = false;
}
else
{
Writer << TEXT(", ");
}
Expr->Write(Writer);
}
switch (Type)
{
case EType::Braced: Writer << TEXT("}"); break;
case EType::Parenthesized: Writer << TEXT(")"); break;
default: break;
}
}
FParameterDeclarator::FParameterDeclarator(FLinearAllocator* InAllocator, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
Type(nullptr),
Identifier(nullptr),
Semantic(nullptr),
bIsArray(false),
ArraySize(InAllocator),
DefaultValue(nullptr)
{
}
void FParameterDeclarator::Write(FASTWriter& Writer) const
{
WriteAttributes(Writer);
Type->Write(Writer);
Writer << (TCHAR)' ' << Identifier;
WriteOptionArraySize(Writer, bIsArray, ArraySize);
if (Semantic)
{
Semantic->Write(Writer);
}
if (DefaultValue)
{
Writer << TEXT(" = ");
DefaultValue->Write(Writer);
}
}
FParameterDeclarator* FParameterDeclarator::CreateFromDeclaratorList(FDeclaratorList* List, FLinearAllocator* Allocator)
{
check(List);
check(List->Declarations.Num() == 1);
auto* Source = (FDeclaration*)List->Declarations[0];
auto* New = new(Allocator) FParameterDeclarator(Allocator, Source->SourceInfo);
New->Type = List->Type;
New->Identifier = Source->Identifier;
New->Semantic = Source->Semantic;
New->bIsArray = Source->bIsArray;
New->ArraySize = Source->ArraySize;
New->DefaultValue = Source->Initializer;
return New;
}
FParameterDeclarator::~FParameterDeclarator()
{
delete Type;
for (auto* Expr : ArraySize)
{
delete Expr;
}
if (DefaultValue)
{
delete DefaultValue;
}
}
FIterationStatement::FIterationStatement(FLinearAllocator* InAllocator, const FSourceInfo& InInfo, EIterationType InType) :
FNode(InAllocator, InInfo),
Type(InType),
InitStatement(nullptr),
Condition(nullptr),
RestExpression(nullptr),
Body(nullptr)
{
}
void FIterationStatement::Write(FASTWriter& Writer) const
{
Writer.DoIndent();
WriteAttributes(Writer);
switch (Type)
{
case EIterationType::For:
Writer << TEXT("for (");
if (InitStatement)
{
auto* DeclList = InitStatement->AsDeclaratorList();
if (DeclList)
{
DeclList->WriteNoEOL(Writer);
}
else
{
InitStatement->Write(Writer);
Writer << TEXT(";");
}
}
else
{
Writer << TEXT(" ;");
}
Writer << TEXT(" ");
if (Condition)
{
Condition->Write(Writer);
}
Writer << TEXT("; ");
if (RestExpression)
{
RestExpression->Write(Writer);
}
Writer << TEXT(")\n");
if (Body)
{
Body->Write(Writer);
}
else
{
Writer.DoIndent();
Writer << TEXT("{\n");
Writer.DoIndent();
Writer << TEXT("}\n");
}
break;
case EIterationType::While:
Writer << TEXT("while (");
Condition->Write(Writer);
Writer << TEXT(")\n");
Writer.DoIndent();
Writer << TEXT("{\n");
if (Body)
{
FASTWriterIncrementScope Scope(Writer);
Body->Write(Writer);
}
Writer.DoIndent();
Writer << TEXT("}\n");
break;
case EIterationType::DoWhile:
Writer << TEXT("do\n");
Writer.DoIndent();
Writer << TEXT("{\n");
if (Body)
{
FASTWriterIncrementScope Scope(Writer);
Body->Write(Writer);
}
Writer.DoIndent();
Writer << TEXT("}\n");
Writer.DoIndent();
Writer << TEXT("while (");
Condition->Write(Writer);
Writer << TEXT(");\n");
break;
default:
checkf(0, TEXT("Unhandled AST iteration type %d!"), (int32)Type);
break;
}
}
FIterationStatement::~FIterationStatement()
{
if (InitStatement)
{
delete InitStatement;
}
if (Condition)
{
delete Condition;
}
if (RestExpression)
{
delete RestExpression;
}
if (Body)
{
delete Body;
}
}
FFunctionExpression::FFunctionExpression(FLinearAllocator* InAllocator, const FSourceInfo& InInfo, FExpression* InCallee) :
FExpression(InAllocator, EOperators::FunctionCall, InInfo)
, Callee(InCallee)
{
}
void FFunctionExpression::Write(FASTWriter& Writer) const
{
Callee->Write(Writer);
Writer << (TCHAR)'(';
bool bFirst = true;
for (auto* Expr : Expressions)
{
if (bFirst)
{
bFirst = false;
}
else
{
Writer << TEXT(", ");
}
Expr->Write(Writer);
}
Writer << TEXT(")");
}
FSwitchStatement::FSwitchStatement(FLinearAllocator* InAllocator, const FSourceInfo& InInfo, FExpression* InCondition, FSwitchBody* InBody) :
FNode(InAllocator, InInfo),
Condition(InCondition),
Body(InBody)
{
}
void FSwitchStatement::Write(FASTWriter& Writer) const
{
Writer.DoIndent();
Writer << TEXT("switch (");
Condition->Write(Writer);
Writer << TEXT(")\n");
Body->Write(Writer);
}
FSwitchStatement::~FSwitchStatement()
{
delete Condition;
delete Body;
}
FSwitchBody::FSwitchBody(FLinearAllocator* InAllocator, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
CaseList(nullptr)
{
}
void FSwitchBody::Write(FASTWriter& Writer) const
{
Writer.DoIndent();
Writer << TEXT("{\n");
{
FASTWriterIncrementScope Scope(Writer);
CaseList->Write(Writer);
}
Writer.DoIndent();
Writer << TEXT("}\n");
}
FSwitchBody::~FSwitchBody()
{
delete CaseList;
}
FCaseLabel::FCaseLabel(FLinearAllocator* InAllocator, const FSourceInfo& InInfo, AST::FExpression* InExpression) :
FNode(InAllocator, InInfo),
TestExpression(InExpression)
{
}
void FCaseLabel::Write(FASTWriter& Writer) const
{
Writer.DoIndent();
if (TestExpression)
{
Writer << TEXT("case ");
TestExpression->Write(Writer);
}
else
{
Writer << TEXT("default");
}
Writer << TEXT(":\n");
}
FCaseLabel::~FCaseLabel()
{
if (TestExpression)
{
delete TestExpression;
}
}
FCaseStatement::FCaseStatement(FLinearAllocator* InAllocator, const FSourceInfo& InInfo, FCaseLabelList* InLabels) :
FNode(InAllocator, InInfo),
Labels(InLabels),
Statements(InAllocator)
{
}
void FCaseStatement::Write(FASTWriter& Writer) const
{
Labels->Write(Writer);
if (Statements.Num() > 1)
{
Writer.DoIndent();
Writer << TEXT("{\n");
for (auto* Statement : Statements)
{
FASTWriterIncrementScope Scope(Writer);
Statement->Write(Writer);
}
Writer.DoIndent();
Writer << TEXT("}\n");
}
else if (Statements.Num() > 0)
{
FASTWriterIncrementScope Scope(Writer);
Statements[0]->Write(Writer);
}
}
FCaseStatement::~FCaseStatement()
{
delete Labels;
for (auto* Statement : Statements)
{
if (Statement)
{
delete Statement;
}
}
}
FCaseLabelList::FCaseLabelList(FLinearAllocator* InAllocator, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
Labels(InAllocator)
{
}
void FCaseLabelList::Write(FASTWriter& Writer) const
{
for (auto* Label : Labels)
{
Label->Write(Writer);
}
}
FCaseLabelList::~FCaseLabelList()
{
for (auto* Label : Labels)
{
delete Label;
}
}
FCaseStatementList::FCaseStatementList(FLinearAllocator* InAllocator, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
Cases(InAllocator)
{
}
void FCaseStatementList::Write(FASTWriter& Writer) const
{
for (auto* Case : Cases)
{
Case->Write(Writer);
}
}
FCaseStatementList::~FCaseStatementList()
{
for (auto* Case : Cases)
{
delete Case;
}
}
FStructSpecifier::FStructSpecifier(FLinearAllocator* InAllocator, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
Name(nullptr),
ParentName(nullptr),
Members(InAllocator),
bForwardDeclaration(false)
{
}
void FStructSpecifier::Write(FASTWriter& Writer) const
{
Writer << TEXT("struct ");
Writer << (Name ? Name : TEXT(""));
if (ParentName && *ParentName)
{
Writer << TEXT(" : ");
Writer << ParentName;
}
if (bForwardDeclaration)
{
Writer << TEXT(";\n");
}
else
{
Writer << TEXT('\n');
Writer.DoIndent();
Writer << TEXT("{\n");
for (auto* Member : Members)
{
FASTWriterIncrementScope Scope(Writer);
Member->Write(Writer);
}
Writer.DoIndent();
Writer << TEXT("}");
}
}
FStructSpecifier::~FStructSpecifier()
{
for (auto* Member : Members)
{
delete Member;
}
}
FAttribute::FAttribute(FLinearAllocator* InAllocator, const FSourceInfo& InInfo, const TCHAR* InName) :
FNode(InAllocator, InInfo),
Name(InName),
Arguments(InAllocator)
{
}
void FAttribute::Write(FASTWriter& Writer) const
{
Writer << (TCHAR)'[';
Writer << Name;
bool bFirst = true;
for (auto* Arg : Arguments)
{
if (bFirst)
{
Writer << (TCHAR)'(';
bFirst = false;
}
else
{
Writer << TEXT(", ");
}
Arg->Write(Writer);
}
if (!bFirst)
{
Writer << TEXT(")");
}
Writer << TEXT("]");
}
FAttribute::~FAttribute()
{
for (auto* Arg : Arguments)
{
delete Arg;
}
}
FAttributeArgument::FAttributeArgument(FLinearAllocator* InAllocator, const FSourceInfo& InInfo) :
FNode(InAllocator, InInfo),
StringArgument(nullptr),
ExpressionArgument(nullptr)
{
}
void FAttributeArgument::Write(FASTWriter& Writer) const
{
if (ExpressionArgument)
{
ExpressionArgument->Write(Writer);
}
else
{
Writer << (TCHAR)'"';
Writer << StringArgument;
Writer << (TCHAR)'"';
}
}
FAttributeArgument::~FAttributeArgument()
{
if (ExpressionArgument)
{
delete ExpressionArgument;
}
}
}
}