15#ifdef INK_ENABLE_UNREAL
16# include "../InkVar.h"
19namespace ink::runtime::internal
21class basic_eval_stack;
29 virtual ~callback_base() =
default;
33class callback final :
public callback_base
35 using traits = function_traits<F>;
36 static_assert(traits::arity < 3);
38 template<ink::runtime::value::Type Ty>
41 if constexpr (traits::arity == 2) {
42 if (old_val.has_value()) {
45 typename traits::template argument<1>::type{old_val.value().get<Ty>()}
51 functor(new_val.
get<Ty>());
56 callback(
const callback&) =
delete;
57 callback(callback&&) =
delete;
58 callback& operator=(
const callback&) =
delete;
59 callback& operator=(callback&&) =
delete;
68 using value = ink::runtime::value;
69 auto check_type = [&new_val, &old_val](
value::Type type) {
71 new_val.
type == type,
"Missmatch type for variable observer: expected %i, got %i",
72 static_cast<int>(type),
static_cast<int>(new_val.
type)
74 if constexpr (traits::arity == 2) {
75 if (old_val.has_value() && old_val.value().type != type) {
77 "Missmatch type for variable observers old value: expected optional<%i> got "
79 static_cast<int>(type),
static_cast<int>(old_val.value().type)
84 if constexpr (traits::arity > 0) {
85 using arg_t =
typename remove_cvref<typename traits::template argument<0>::type>::type;
86 if constexpr (is_same<arg_t, value>::value) {
87 if constexpr (traits::arity == 2) {
88 functor(new_val, old_val);
92 }
else if constexpr (is_same<arg_t, bool>::value) {
94 call_functor<value::Type::Bool>(new_val, old_val);
95 }
else if constexpr (is_same<arg_t, uint32_t>::value) {
97 call_functor<value::Type::Uint32>(new_val, old_val);
98 }
else if constexpr (is_same<arg_t, int32_t>::value) {
100 call_functor<value::Type::Int32>(new_val, old_val);
101 }
else if constexpr (is_same<arg_t, const char*>::value) {
103 call_functor<value::Type::String>(new_val, old_val);
104 }
else if constexpr (is_same<arg_t, float>::value) {
106 call_functor<value::Type::Float>(new_val, old_val);
107 }
else if constexpr (is_same<arg_t, list_interface*>::value) {
109 call_functor<value::Type::List>(new_val, old_val);
112 always_false<arg_t>::value,
"Unsupported value for variable observer callback!"
128 function_base(
bool lookaheadSafe)
129 : _lookaheadSafe(lookaheadSafe)
133 virtual ~function_base() {}
137#ifdef INK_ENABLE_UNREAL
139 call(basic_eval_stack* stack,
size_t length, string_table& strings, list_table& lists)
143 call(basic_eval_stack* stack,
size_t length, string_table& strings, list_table& lists)
147 bool lookaheadSafe()
const {
return _lookaheadSafe; }
153 static T pop(basic_eval_stack* stack, list_table& lists);
157 static void push(basic_eval_stack* stack,
const T& value);
159 static void push_void(basic_eval_stack* stack);
162 static void push_string(basic_eval_stack* stack,
const char* dynamic_string);
165 static char* allocate(string_table& strings,
ink::size_t len);
170class function :
public function_base
173 function(F functor,
bool lookaheadSafe)
174 : function_base(lookaheadSafe)
181 basic_eval_stack* stack,
size_t length, string_table& strings, list_table& lists
184 call(stack, length, strings, lists, GenSeq<traits::arity>());
192 using traits = function_traits<F>;
196 using arg_type =
typename function_traits<F>::template argument<index>::type;
200 arg_type<index> pop_arg(basic_eval_stack* stack, list_table& lists)
203 return pop<arg_type<index>>(stack, lists);
206 static constexpr bool is_array_call()
208 if constexpr (traits::arity == 2) {
210 const ink::runtime::value*,
typename traits::template argument<1>::type>::value;
216 template<
size_t... Is>
218 call(basic_eval_stack* stack,
size_t length, string_table& strings, list_table& lists, seq<Is...>)
221 is_array_call() ||
sizeof...(Is) == length,
222 "Attempting to call functor with too few/many arguments"
224 static_assert(
sizeof...(Is) == traits::arity);
226 if constexpr (is_array_call()) {
229 "AIttampt to call array call with more arguments then supportet, please change in "
232 for (
size_t i = 0; i < length; ++i) {
233 vals[i] = pop<ink::runtime::value>(stack, lists);
237 if constexpr (is_same<void, typename traits::return_type>::value) {
239 if constexpr (is_array_call()) {
240 functor(length, vals);
242 functor(pop_arg<Is>(stack, lists)...);
248 typename traits::return_type res;
249 if constexpr (is_array_call()) {
250 res = functor(length, vals);
252 res = functor(pop_arg<Is>(stack, lists)...);
254 if constexpr (is_string<typename traits::return_type>::value) {
259 size_t len = string_handler<typename traits::return_type>::length(res);
262 char* buffer = allocate(strings, len + 1);
263 string_handler<typename traits::return_type>::src_copy(res, buffer);
266 push_string(stack, buffer);
267 }
else if constexpr (is_same<value, remove_cvref<typename traits::return_type>>::value) {
269 auto src = res.template get<ink::runtime::value::Type::String>();
270 size_t len = string_handler<
decltype(src)>::length(src);
271 char* buffer = allocate(strings, len + 1);
272 string_handler<
decltype(src)>::src_copy(src, buffer);
273 push_string(stack, buffer);
285#ifdef INK_ENABLE_UNREAL
287class function_array_delegate :
public function_base
290 function_array_delegate(
const D& del,
bool lookaheadSafe)
291 : function_base(lookaheadSafe)
292 , invocableDelegate(del)
298 basic_eval_stack* stack,
size_t length, string_table& strings, list_table& lists
301 constexpr bool RET_VOID
302 = is_same<
typename function_traits<
decltype(&D::Execute)>::return_type,
void>::value;
304 TArray<FInkVar> variables;
305 for (
size_t i = 0; i < length; i++) {
306 variables.Add(pop<FInkVar>(stack, lists));
308 if constexpr (RET_VOID) {
309 invocableDelegate.Execute(variables);
313 auto ret = invocableDelegate.Execute(variables);
314 ink::runtime::value result = ret.to_value();
317 size_t len = string_handler<const char*>::length(src);
318 char* buffer = allocate(strings, len + 1);
323 result = ink::runtime::value(buffer);
#define inkFail(text,...)
Compile argument agnostic assert macro (always asserts).
Definition system.h:59
#define inkAssert(condition, text,...)
Compile argument agnostic assert macro.
Definition system.h:58
constexpr int maxArrayCallArity
max number of arguments for external functions (dynamic not possible).
Definition config.h:81
std::optional< T > optional
custom optional implementation for usage if STL is disabled
Definition system.h:335
unsigned int size_t
Used for the size of arrays.
Definition system.h:113
constexpr std::nullopt_t nullopt
an empty optional
Definition system.h:337
Type
Type labels for ink::runtime::value.
Definition types.h:49
@ Float
containing a float
Definition types.h:54
@ String
contaning a const char*
Definition types.h:53
@ Uint32
containing uint32_t
Definition types.h:51
@ List
containing a list_interface
Definition types.h:55
@ Int32
containing int32_t
Definition types.h:52
@ Bool
containing bool
Definition types.h:50
enum ink::runtime::value::Type type
Label of type currently contained in value.
const auto & get() const
Get value to corresponding type.
Definition types.h:141