ZoneCodeGenerator: Add Evaluation as basis for specifying conditions and counts

This commit is contained in:
Jan 2019-10-02 15:47:24 +02:00
parent 61eb92588e
commit 785e2c9bfb
10 changed files with 271 additions and 22 deletions

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ZoneCodeGenerator.Domain.Evaluation
{
interface IEvaluation
{
bool IsStatic { get; }
int EvaluateNumeric();
}
}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ZoneCodeGenerator.Domain.Evaluation
{
class OperandDynamic : IEvaluation
{
public bool IsStatic => false;
public int EvaluateNumeric()
{
throw new Exception("A dynamic operand cannot be evaluated.");
}
}
}

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ZoneCodeGenerator.Domain.Evaluation
{
class OperandStatic : IEvaluation
{
public int Value { get; }
public bool IsStatic => true;
public int EvaluateNumeric()
{
return Value;
}
public OperandStatic(int value)
{
Value = value;
}
}
}

View File

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ZoneCodeGenerator.Domain.Evaluation
{
class Operation : IEvaluation
{
public IEvaluation Operand1 { get; }
public IEvaluation Operand2 { get; }
public OperationType OperationType { get; }
public bool IsStatic => Operand1.IsStatic && Operand2.IsStatic;
public int EvaluateNumeric()
{
return OperationType.Function(Operand1.EvaluateNumeric(), Operand2.EvaluateNumeric());
}
public Operation(IEvaluation operand1, IEvaluation operand2, OperationType type)
{
Operand1 = operand1;
Operand2 = operand2;
OperationType = type;
}
}
}

View File

@ -0,0 +1,138 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace ZoneCodeGenerator.Domain.Evaluation
{
sealed class OperationType
{
// https://en.cppreference.com/w/cpp/language/operator_precedence
public enum OperationPrecedence
{
MultiplicationDivisionRemainder = 1,
AdditionSubtraction = 2,
BitwiseShift = 3,
RelationalGreaterLessThan = 4,
RelationalEquals = 5,
LogicalAnd = 6,
LogicalOr = 7
}
public delegate int EvaluationFunction(int operand1, int operand2);
public string Syntax { get; }
public OperationPrecedence Precedence { get; }
public EvaluationFunction Function { get; }
public override string ToString()
{
return Syntax;
}
private OperationType(string syntax, OperationPrecedence precedence, EvaluationFunction function)
{
Syntax = syntax;
Precedence = precedence;
Function = function;
}
public static OperationType OperationAdd = new OperationType(
"+",
OperationPrecedence.AdditionSubtraction,
(operand1, operand2) => operand1 + operand2
);
public static OperationType OperationSubtract = new OperationType(
"-",
OperationPrecedence.AdditionSubtraction,
(operand1, operand2) => operand1 - operand2
);
public static OperationType OperationMultiply = new OperationType(
"*",
OperationPrecedence.MultiplicationDivisionRemainder,
(operand1, operand2) => operand1 * operand2
);
public static OperationType OperationDivide = new OperationType(
"/",
OperationPrecedence.MultiplicationDivisionRemainder,
(operand1, operand2) => operand1 / operand2
);
public static OperationType OperationRemainder = new OperationType(
"%",
OperationPrecedence.MultiplicationDivisionRemainder,
(operand1, operand2) => operand1 % operand2
);
public static OperationType OperationShiftLeft = new OperationType(
"<<",
OperationPrecedence.BitwiseShift,
(operand1, operand2) => operand1 << operand2
);
public static OperationType OperationShiftRight = new OperationType(
">>",
OperationPrecedence.BitwiseShift,
(operand1, operand2) => operand1 >> operand2
);
public static OperationType OperationGreaterThan = new OperationType(
">",
OperationPrecedence.RelationalGreaterLessThan,
(operand1, operand2) => operand1 > operand2 ? 1 : 0
);
public static OperationType OperationGreaterEqualsThan = new OperationType(
">=",
OperationPrecedence.RelationalGreaterLessThan,
(operand1, operand2) => operand1 >= operand2 ? 1 : 0
);
public static OperationType OperationLessThan = new OperationType(
"<",
OperationPrecedence.RelationalGreaterLessThan,
(operand1, operand2) => operand1 < operand2 ? 1 : 0
);
public static OperationType OperationLessEqualsThan = new OperationType(
"<=",
OperationPrecedence.RelationalGreaterLessThan,
(operand1, operand2) => operand1 <= operand2 ? 1 : 0
);
public static OperationType OperationEquals = new OperationType(
"==",
OperationPrecedence.RelationalEquals,
(operand1, operand2) => operand1 == operand2 ? 1 : 0
);
public static OperationType OperationNotEquals = new OperationType(
"!=",
OperationPrecedence.RelationalEquals,
(operand1, operand2) => operand1 != operand2 ? 1 : 0
);
public static OperationType OperationAnd = new OperationType(
"&&",
OperationPrecedence.LogicalAnd,
(operand1, operand2) => operand1 > 0 && operand2 > 0 ? 1 : 0
);
public static OperationType OperationOr = new OperationType(
"||",
OperationPrecedence.LogicalOr,
(operand1, operand2) => operand1 > 0 || operand2 > 0 ? 1 : 0
);
public static List<OperationType> Types => typeof(OperationType)
.GetFields(BindingFlags.Static | BindingFlags.Public)
.Select(info => info.GetValue(null))
.OfType<OperationType>()
.ToList();
}
}

View File

@ -1,6 +1,14 @@
namespace ZoneCodeGenerator.Domain
using System;
using ZoneCodeGenerator.Domain.Evaluation;
namespace ZoneCodeGenerator.Domain
{
class ReferenceTypePointer : ReferenceType
{
public static IEvaluation DefaultCount = new OperandStatic(1);
public IEvaluation Count { get; set; } = DefaultCount;
public bool IsArray => !Count.IsStatic || Count.EvaluateNumeric() > 1;
}
}

View File

@ -26,7 +26,8 @@ namespace ZoneCodeGenerator.Domain.StructureInformation
public List<StructureInformation> Usages { get; }
public List<MemberInformation> OrderedMembers { get; }
public bool NonEmbeddedReferenceExists { get; set; }
public bool PointerReferenceExists { get; set; }
public bool SinglePointerReferenceExists { get; set; }
public bool ArrayPointerReferenceExists { get; set; }
public bool ArrayReferenceExists { get; set; }
public bool HasNameMember => Type.Members.Any(variable => variable.Name.Equals("name", StringComparison.CurrentCultureIgnoreCase));
@ -37,7 +38,7 @@ namespace ZoneCodeGenerator.Domain.StructureInformation
fastFileAlign = null;
Type = type;
NonEmbeddedReferenceExists = false;
PointerReferenceExists = false;
SinglePointerReferenceExists = false;
ArrayReferenceExists = false;
Usages = new List<StructureInformation>();
OrderedMembers = new List<MemberInformation>();

View File

@ -9,21 +9,21 @@ LoaderClassName(asset) ::= "Loader_$asset.Type.Name$"
HeaderConstructor(context) ::= "$LoaderClassName(context.Asset)$(IZoneScriptStringProvider* scriptStringProvider, Zone* zone, IZoneInputStream* stream);"
HeaderPtrLoadMethodDeclaration(structure) ::= "void LoadPtr_$structure.Type.Name$($structure.Type.FullName$** pPtr);"
HeaderArrayLoadMethodDeclaration(structure) ::= "void LoadArray_$structure.Type.Name$($structure.Type.FullName$** pArray, size_t count, bool atStreamStart);"
HeaderSinglePtrLoadMethodDeclaration(structure) ::= "void LoadPtr_$structure.Type.Name$($structure.Type.FullName$** pPtr);"
HeaderArrayPtrLoadMethodDeclaration(structure) ::= "void LoadArray_$structure.Type.Name$($structure.Type.FullName$** pArray, size_t count, bool atStreamStart);"
HeaderLoadMethodDeclaration(structure) ::= "void Load_$structure.Type.Name$($structure.Type.FullName$* p$structure.Type.Name$, bool atStreamStart);"
HeaderGetNameMethodDeclaration(asset) ::= "static std::string GetAssetName($asset.Type.FullName$* p$asset.Type.Name$);"
HeaderAssetLoadMethodDeclaration(asset) ::= "void LoadAsset_$asset.Type.Name$($asset.Type.FullName$** pPtr);"
HeaderDeclaration(structure) ::= <%
$if(structure.PointerReferenceExists)$
$HeaderPtrLoadMethodDeclaration(structure)$
$if(structure.SinglePointerReferenceExists)$
$HeaderSinglePtrLoadMethodDeclaration(structure)$
$\n$
$endif$
$if(structure.ArrayReferenceExists)$
$HeaderArrayLoadMethodDeclaration(structure)$
$if(structure.ArrayPointerReferenceExists)$
$HeaderArrayPtrLoadMethodDeclaration(structure)$
$\n$
$endif$
@ -60,7 +60,7 @@ namespace $context.Game$
public:
$HeaderConstructor(context)$
$HeaderPtrLoadMethodDeclaration(context.Asset)$
$HeaderSinglePtrLoadMethodDeclaration(context.Asset)$
$HeaderGetNameMethodDeclaration(context.Asset)$
};
}
@ -91,7 +91,7 @@ void $LoaderClassName(context.Asset)$::Load_$structure.Type.Name$($structure.Typ
}
>>
LoadPtrMethod(structure, context) ::= <<
LoadSinglePtrMethod(structure, context) ::= <<
void $LoaderClassName(context.Asset)$::LoadPtr_$structure.Type.Name$($structure.Type.FullName$** pPtr)
{
assert(pPtr != nullptr);
@ -141,7 +141,7 @@ void $LoaderClassName(context.Asset)$::LoadPtr_$structure.Type.Name$($structure.
}
>>
LoadArrayMethod(structure, context) ::= <<
LoadArrayPtrMethod(structure, context) ::= <<
void $LoaderClassName(context.Asset)$::LoadArray_$structure.Type.Name$($structure.Type.FullName$** pArray, const size_t count, const bool atStreamStart)
{
assert(pArray != nullptr);
@ -161,12 +161,12 @@ $if(structure.NonEmbeddedReferenceExists)$
$LoadMethod(structure, context)$
$endif$
$if(structure.PointerReferenceExists)$
$LoadPtrMethod(structure, context)$
$if(structure.SinglePointerReferenceExists)$
$LoadSinglePtrMethod(structure, context)$
$endif$
$if(structure.ArrayReferenceExists)$
$LoadArrayMethod(structure, context)$
$if(structure.ArrayPointerReferenceExists)$
$LoadArrayPtrMethod(structure, context)$
$endif$
>>
@ -220,7 +220,7 @@ $LoadMethod(context.Asset, context)$
$LoadAssetMethod(context.Asset, context)$
$LoadPtrMethod(context.Asset, context)$
$LoadSinglePtrMethod(context.Asset, context)$
$GetNameMethod(context)$
>>

View File

@ -23,11 +23,14 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.PostProcessor
if (IsNonEmbeddedReference(memberInformation.Member))
memberInformation.StructureType.NonEmbeddedReferenceExists = true;
if (IsPointerReference(memberInformation.Member))
memberInformation.StructureType.PointerReferenceExists = true;
if (IsSinglePointerReference(memberInformation.Member))
memberInformation.StructureType.SinglePointerReferenceExists = true;
if (IsArrayPointerReference(memberInformation.Member))
memberInformation.StructureType.ArrayPointerReferenceExists = true;
if (IsArrayReference(memberInformation.Member))
memberInformation.StructureType.PointerReferenceExists = true;
memberInformation.StructureType.ArrayReferenceExists = true;
}
}
@ -39,10 +42,18 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.PostProcessor
return var.VariableType.References.Any();
}
private static bool IsPointerReference(Variable var)
private static bool IsSinglePointerReference(Variable var)
{
return var.VariableType.References.Any()
&& var.VariableType.References.Last() is ReferenceTypePointer;
&& var.VariableType.References.Last() is ReferenceTypePointer pointerReference
&& !pointerReference.IsArray;
}
private static bool IsArrayPointerReference(Variable var)
{
return var.VariableType.References.Any()
&& var.VariableType.References.Last() is ReferenceTypePointer pointerReference
&& pointerReference.IsArray;
}
private static bool IsArrayReference(Variable var)

View File

@ -63,6 +63,11 @@
<Compile Include="Domain\DataTypeUnion.cs" />
<Compile Include="Domain\DataTypeWithMembers.cs" />
<Compile Include="Domain\EnumMember.cs" />
<Compile Include="Domain\Evaluation\IEvaluation.cs" />
<Compile Include="Domain\Evaluation\OperandDynamic.cs" />
<Compile Include="Domain\Evaluation\OperandStatic.cs" />
<Compile Include="Domain\Evaluation\Operation.cs" />
<Compile Include="Domain\Evaluation\OperationType.cs" />
<Compile Include="Domain\FastFileStructure\FastFileBlock.cs" />
<Compile Include="Domain\ForwardDeclaration.cs" />
<Compile Include="Domain\Namespace.cs" />
@ -169,5 +174,6 @@
<EmbeddedResource Include="Generating\Templates\AssetStructTests.stg" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>