Ark Server API (ASA) - Wiki
Loading...
Searching...
No Matches
ExpressionParserTypes.inl
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreFwd.h"
6#include "Templates/RemoveReference.h"
7#include "Templates/PointerIsConvertibleFromTo.h"
8
9#define LOCTEXT_NAMESPACE "ExpressionParser"
10
11class FExpressionNode;
14template< class T > struct TRemoveConst;
15
16namespace Impl
17{
18 /** Interface for a wrapper utility for any moveable/copyable data */
20 {
22 /** Move this type into another unallocated buffer (move-construct a new type from our wrapped value) */
23 virtual void Reseat(uint8* Dst) = 0;
24 /** Move this type to a buffer already allocated to the same type (uses type-defined move-assignment) */
25 virtual void MoveAssign(uint8* Dst) = 0;
26 /** Copy this data */
27 virtual FExpressionNode Copy() const = 0;
28 };
29
30 /** Implementation of the wrapper utility for any moveable/copyable data, that allows us to virtually move/copy/destruct the data */
31 /** Data is stored inline in this implementation, for efficiency */
32 template<typename T>
34 {
35 /** The data itself, allocated on the stack */
37
38 /** Constructor/destructor */
41
42 const T* Access() const { return &Value; }
43
44 virtual void Reseat(uint8* Dst) override { new(Dst) FInlineDataStorage(MoveTemp(Value)); }
45 virtual void MoveAssign(uint8* Dst) override { reinterpret_cast<FInlineDataStorage*>(Dst)->Value = MoveTemp(Value); }
46 virtual FExpressionNode Copy() const override { return Value; }
47 };
48
49 /** Data is stored on the heap in this implementation */
50 template<typename T>
52 {
53 /** The data itself, allocated on the heap */
55
56 /** Constructor/destructor */
57 FHeapDataStorage(T InValue) : Value(new T(MoveTemp(InValue))) {}
60
61 const T* Access() const { return Value.Get(); }
62
63 virtual void Reseat(uint8* Dst) override { new(Dst) FHeapDataStorage(MoveTemp(*this)); }
64 virtual void MoveAssign(uint8* Dst) override { reinterpret_cast<FHeapDataStorage*>(Dst)->Value = MoveTemp(Value); }
65 virtual FExpressionNode Copy() const override { return *Value; }
66 };
67
68 template<typename T, uint32 MaxStackAllocationSize, typename Enabled=void> struct TStorageTypeDeduction;
70 { typedef FInlineDataStorage<T> Type; };
72 { typedef FHeapDataStorage<T> Type; };
73
74
75 /** Machinery required for operator mapping */
76 template <typename> struct TCallableInfo;
77 template <typename> struct TCallableInfoImpl;
78
79 template <typename Ret_, typename T, typename Arg1_>
80 struct TCallableInfoImpl<Ret_ (T::*)(Arg1_)> { typedef Ret_ Ret; typedef Arg1_ Arg1; enum { NumArgs = 1 }; };
81 template <typename Ret_, typename T, typename Arg1_>
82 struct TCallableInfoImpl<Ret_ (T::*)(Arg1_) const> { typedef Ret_ Ret; typedef Arg1_ Arg1; enum { NumArgs = 1 }; };
83
84 template <typename Ret_, typename T, typename Arg1_, typename Arg2_>
85 struct TCallableInfoImpl<Ret_ (T::*)(Arg1_, Arg2_)> { typedef Ret_ Ret; typedef Arg1_ Arg1; typedef Arg2_ Arg2; enum { NumArgs = 2 }; };
86 template <typename Ret_, typename T, typename Arg1_, typename Arg2_>
87 struct TCallableInfoImpl<Ret_ (T::*)(Arg1_, Arg2_) const> { typedef Ret_ Ret; typedef Arg1_ Arg1; typedef Arg2_ Arg2; enum { NumArgs = 2 }; };
88
89 template <typename Ret_, typename T, typename Arg1_, typename Arg2_, typename Arg3_>
90 struct TCallableInfoImpl<Ret_ (T::*)(Arg1_, Arg2_, Arg3_)> { typedef Ret_ Ret; typedef Arg1_ Arg1; typedef Arg2_ Arg2; typedef Arg3_ Arg3; enum { NumArgs = 3 }; };
91 template <typename Ret_, typename T, typename Arg1_, typename Arg2_, typename Arg3_>
92 struct TCallableInfoImpl<Ret_ (T::*)(Arg1_, Arg2_, Arg3_) const> { typedef Ret_ Ret; typedef Arg1_ Arg1; typedef Arg2_ Arg2; typedef Arg3_ Arg3; enum { NumArgs = 3 }; };
93
94 /** @todo: decltype(&T::operator()) can go directly in the specialization below if it weren't for VS2012 support */
95 template<typename T>
96 struct TGetOperatorCallPtr { typedef decltype(&T::operator()) Type; };
97
98 template <typename T>
99 struct TCallableInfo : TCallableInfoImpl<typename TGetOperatorCallPtr<T>::Type> {};
100
101 /** Overloaded function that returns an FExpressionResult, regardless of what is passed in */
102 template<typename T>
104 static FExpressionResult ForwardReturnType(FExpressionResult&& Result) { return MoveTemp(Result); }
105
106 /** Wrapper function for supplied functions of the signature T(A) */
107 template<typename OperandType, typename ContextType, typename FuncType>
109 {
110 // Ignore the context
111 return [=](const FExpressionNode& InOperand, const ContextType* Context) {
113 };
114 }
115
116 /** Wrapper function for supplied functions of the signature T(A, const ContextType* Context) */
117 template<typename OperandType, typename ContextType, typename FuncType>
119 {
120 // Ignore the context
121 return [=](const FExpressionNode& InOperand, const ContextType* Context) {
123 };
124 }
125
126 /** Wrapper function for supplied functions of the signature T(A, B) */
127 template<typename LeftOperandType, typename RightOperandType, typename ContextType, typename FuncType>
129 {
130 // Ignore the context
133 };
134 }
135
136 /** Wrapper function for supplied functions of the signature T(A, B, const ContextType* Context) */
137 template<typename LeftOperandType, typename RightOperandType, typename ContextType, typename FuncType>
139 {
140 // Ignore the context
143 };
144 }
145
146 /** Wrapper function for supplied functions of the signature bool(A, const ContextType* Context) */
147 template<typename OperandType, typename ContextType, typename FuncType>
149 {
150 // Ignore the context
151 return [=](const FExpressionNode& InOperand, const ContextType* Context) {
152 return In(*InOperand.Cast<OperandType>());
153 };
154 }
155
156 /** Wrapper function for supplied functions of the signature bool(A, const ContextType* Context) */
157 template<typename OperandType, typename ContextType, typename FuncType>
159 {
160 // Ignore the context
161 return [=](const FExpressionNode& InOperand, const ContextType* Context) {
162 return In(*InOperand.Cast<OperandType>(), Context);
163 };
164 }
165}
166
167template<typename T>
168FExpressionNode::FExpressionNode(T In, typename TEnableIf<!TPointerIsConvertibleFromTo<T,FExpressionNode>::Value>::Type*)
169 : TypeId(TGetExpressionNodeTypeId<T>::GetTypeId())
170{
171 // Choose the relevant allocation strategy based on the size of the type
172 new(InlineBytes) typename Impl::TStorageTypeDeduction<T, MaxStackAllocationSize>::Type(MoveTemp(In));
173}
174
175template<typename T>
176const T* FExpressionNode::Cast() const
177{
178 if (TypeId == TGetExpressionNodeTypeId<T>::GetTypeId())
179 {
180 return reinterpret_cast<const typename Impl::TStorageTypeDeduction<T, MaxStackAllocationSize>::Type*>(InlineBytes)->Access();
181 }
182 return nullptr;
183}
184
185// End FExpresionNode
186
187template<typename ContextType>
188FExpressionResult TOperatorJumpTable<ContextType>::ExecBinary(const FExpressionToken& Operator, const FExpressionToken& L, const FExpressionToken& R, const ContextType* Context) const
189{
190 FOperatorFunctionID ID = { Operator.Node.GetTypeId(), L.Node.GetTypeId(), R.Node.GetTypeId() };
191 if (const auto* Func = BinaryOps.Find(ID))
192 {
193 return (*Func)(L.Node, R.Node, Context);
194 }
195
196 FFormatOrderedArguments Args;
197 Args.Add(FText::FromString(Operator.Context.GetString()));
198 Args.Add(FText::FromString(L.Context.GetString()));
199 Args.Add(FText::FromString(R.Context.GetString()));
200 return MakeError(FText::Format(LOCTEXT("BinaryExecutionError", "Binary operator {0} cannot operate on {1} and {2}"), Args));
201}
202
203template<typename ContextType>
204bool TOperatorJumpTable<ContextType>::ShouldShortCircuit(const FExpressionToken& Operator, const FExpressionToken& L, const ContextType* Context) const
205{
206 FOperatorFunctionID ID = { Operator.Node.GetTypeId(), L.Node.GetTypeId(), FGuid() };
207 if (const auto* Func = BinaryShortCircuits.Find(ID))
208 {
209 return (*Func)(L.Node, Context);
210 }
211
212 return false;
213}
214
215template<typename ContextType>
216FExpressionResult TOperatorJumpTable<ContextType>::ExecPreUnary(const FExpressionToken& Operator, const FExpressionToken& R, const ContextType* Context) const
217{
218 FOperatorFunctionID ID = { Operator.Node.GetTypeId(), FGuid(), R.Node.GetTypeId() };
219 if (const auto* Func = PreUnaryOps.Find(ID))
220 {
221 return (*Func)(R.Node, Context);
222 }
223
224 FFormatOrderedArguments Args;
225 Args.Add(FText::FromString(Operator.Context.GetString()));
226 Args.Add(FText::FromString(R.Context.GetString()));
227 return MakeError(FText::Format(LOCTEXT("PreUnaryExecutionError", "Pre-unary operator {0} cannot operate on {1}"), Args));
228}
229
230template<typename ContextType>
231FExpressionResult TOperatorJumpTable<ContextType>::ExecPostUnary(const FExpressionToken& Operator, const FExpressionToken& L, const ContextType* Context) const
232{
233 FOperatorFunctionID ID = { Operator.Node.GetTypeId(), L.Node.GetTypeId(), FGuid() };
234 if (const auto* Func = PostUnaryOps.Find(ID))
235 {
236 return (*Func)(L.Node, Context);
237 }
238
239 FFormatOrderedArguments Args;
240 Args.Add(FText::FromString(Operator.Context.GetString()));
241 Args.Add(FText::FromString(L.Context.GetString()));
242 return MakeError(FText::Format(LOCTEXT("PostUnaryExecutionError", "Post-unary operator {0} cannot operate on {1}"), Args));
243}
244
245template<typename ContextType>
246template<typename OperatorType, typename FuncType>
247void TOperatorJumpTable<ContextType>::MapPreUnary(FuncType InFunc)
248{
249 typedef typename TRemoveConst<typename TRemoveReference<typename Impl::TCallableInfo<FuncType>::Arg1>::Type>::Type OperandType;
250
251 FOperatorFunctionID ID = {
252 TGetExpressionNodeTypeId<OperatorType>::GetTypeId(),
253 FGuid(),
254 TGetExpressionNodeTypeId<OperandType>::GetTypeId()
255 };
256
257 PreUnaryOps.Add(ID, Impl::WrapUnaryFunction<OperandType, ContextType>(InFunc));
258}
259
260template<typename ContextType>
261template<typename OperatorType, typename FuncType>
262void TOperatorJumpTable<ContextType>::MapPostUnary(FuncType InFunc)
263{
264 typedef typename TRemoveConst<typename TRemoveReference<typename Impl::TCallableInfo<FuncType>::Arg1>::Type>::Type OperandType;
265
266 FOperatorFunctionID ID = {
267 TGetExpressionNodeTypeId<OperatorType>::GetTypeId(),
268 TGetExpressionNodeTypeId<OperandType>::GetTypeId(),
269 FGuid()
270 };
271
272 PostUnaryOps.Add(ID, Impl::WrapUnaryFunction<OperandType, ContextType>(InFunc));
273}
274
275template<typename ContextType>
276template<typename OperatorType, typename FuncType>
277void TOperatorJumpTable<ContextType>::MapBinary(FuncType InFunc)
278{
279 typedef typename TRemoveConst<typename TRemoveReference<typename Impl::TCallableInfo<FuncType>::Arg1>::Type>::Type LeftOperandType;
280 typedef typename TRemoveConst<typename TRemoveReference<typename Impl::TCallableInfo<FuncType>::Arg2>::Type>::Type RightOperandType;
281
282 FOperatorFunctionID ID = {
283 TGetExpressionNodeTypeId<OperatorType>::GetTypeId(),
284 TGetExpressionNodeTypeId<LeftOperandType>::GetTypeId(),
285 TGetExpressionNodeTypeId<RightOperandType>::GetTypeId()
286 };
288 BinaryOps.Add(ID, Impl::WrapBinaryFunction<LeftOperandType, RightOperandType, ContextType>(InFunc));
290
291template<typename ContextType>
292template<typename OperatorType, typename FuncType>
293void TOperatorJumpTable<ContextType>::MapShortCircuit(FuncType InFunc)
294{
295 typedef typename TRemoveConst<typename TRemoveReference<typename Impl::TCallableInfo<FuncType>::Arg1>::Type>::Type OperandType;
296
297 FOperatorFunctionID ID = {
298 TGetExpressionNodeTypeId<OperatorType>::GetTypeId(),
299 TGetExpressionNodeTypeId<OperandType>::GetTypeId(),
300 FGuid()
301 };
302
303 BinaryShortCircuits.Add(ID, Impl::WrapShortCircuitFunction<OperandType, ContextType>(InFunc));
304}
305
306
307typedef TOperatorEvaluationEnvironment<> FOperatorEvaluationEnvironment;
308
309#undef LOCTEXT_NAMESPACE
static FExpressionResult ForwardReturnType(FExpressionResult &&Result)
static TEnableIf< Impl::TCallableInfo< FuncType >::NumArgs==1, typenameTOperatorJumpTable< ContextType >::FUnaryFunction >::Type WrapUnaryFunction(FuncType In)
static TEnableIf< Impl::TCallableInfo< FuncType >::NumArgs==1, typenameTOperatorJumpTable< ContextType >::FShortCircuit >::Type WrapShortCircuitFunction(FuncType In)
static FExpressionResult ForwardReturnType(T &&Result)
static TEnableIf< Impl::TCallableInfo< FuncType >::NumArgs==2, typenameTOperatorJumpTable< ContextType >::FBinaryFunction >::Type WrapBinaryFunction(FuncType In)
virtual void MoveAssign(uint8 *Dst) override
virtual FExpressionNode Copy() const override
virtual void Reseat(uint8 *Dst) override
FHeapDataStorage(FHeapDataStorage &&In)
virtual void Reseat(uint8 *Dst) override
virtual FExpressionNode Copy() const override
virtual void MoveAssign(uint8 *Dst) override
virtual void Reseat(uint8 *Dst)=0
virtual void MoveAssign(uint8 *Dst)=0
virtual FExpressionNode Copy() const =0
decltype(&T::operator()) Type