void SkUEDelegate::Instance::invoke_as_method(SkObjectBase * scope_p, SkInvokedBase * caller_p, SkInstance ** result_pp, const SkClosureInvokeInfo & invoke_info, const SkExpressionBase * invoking_expr_p) const
  {
  uint32_t invoked_data_array_size = invoke_info.m_params_p->get_arg_count_total();
  SkInvokedMethod imethod(caller_p, const_cast<Instance *>(this), invoked_data_array_size, a_stack_allocate(invoked_data_array_size, SkInstance*));

  // Store expression debug info for next invoked method/coroutine.
  SKDEBUG_ICALL_STORE_GEXPR(invoking_expr_p);

  // Must be called before calling argument expressions
  SKDEBUG_ICALL_SET_EXPR(&imethod, invoking_expr_p);

  // Append argument list
  imethod.data_append_args_exprs(invoke_info.m_arguments, *invoke_info.m_params_p, scope_p);

  // Hook must be called after argument expressions and before invoke()
  SKDEBUG_HOOK_EXPR(invoking_expr_p, scope_p, &imethod, nullptr, SkDebug::HookContext_peek);

  // Invoke the UE4 function
  SkUEReflectionManager::get()->invoke_k2_delegate(as<SkUEDelegate>(), invoke_info.m_params_p, &imethod, result_pp);

  /* $Revisit - MBreyer Enable this when we support return arguments
  // Bind any return arguments
  if (!invoke_info.m_return_args.is_empty())
    {
    imethod.data_bind_return_args(invoke_info.m_return_args, *invoke_info.m_params_p);
    }
  */
  }
void SkUEBlueprintInterface::exec_coroutine(FFrame & stack, void * const result_p)
  {
  const FunctionEntry & function_entry = static_cast<const FunctionEntry &>(*ms_singleton_p->m_binding_entry_array[stack.CurrentNativeFunction->RepOffset]);
  SK_ASSERTX(function_entry.m_type == BindingType_Function, "BindingEntry has bad type!");
  SK_ASSERTX(function_entry.m_sk_invokable_p->get_invoke_type() == SkInvokable_coroutine, "Must not be coroutine at this point.");

  // Create invoked coroutine
  SkInvokedCoroutine * icoroutine_p = SkInvokedCoroutine::pool_new(static_cast<SkCoroutine *>(function_entry.m_sk_invokable_p));

  // Get instance of this object
  SkInstance * this_p = SkUEEntity::new_instance(stack.Object);

  // Set parameters
  icoroutine_p->reset(SkCall_interval_always, nullptr, this_p, nullptr, nullptr);

  #if defined(SKDEBUG_COMMON)
    // Set with SKDEBUG_ICALL_STORE_GEXPR stored here before calls to argument expressions
    // overwrite it.
    const SkExpressionBase * call_expr_p = SkInvokedContextBase::ms_last_expr_p;
  #endif

  SKDEBUG_ICALL_SET_EXPR(icoroutine_p, call_expr_p);

  // Fill invoked coroutine's argument list
  const SkParamEntry * param_entry_array = function_entry.get_param_entry_array();
  icoroutine_p->data_ensure_size(function_entry.m_num_params);
  for (uint32_t i = 0; i < function_entry.m_num_params; ++i)
    {
    const SkParamEntry & param_entry = param_entry_array[i];
    icoroutine_p->data_append_arg((*param_entry.m_fetcher_p)(stack));
    }

  // Done with stack - now increment the code ptr unless it is null
  stack.Code += !!stack.Code;

  SKDEBUG_HOOK_EXPR(call_expr_p, icoroutine_p, nullptr);

  #if (SKOOKUM & SK_DEBUG)
    if (!this_p->get_class()->is_class(*function_entry.m_sk_class_p))
      {
      SK_ERRORX(a_str_format("Attempted to invoke coroutine '%s@%s' via a blueprint of type '%s'. You might have forgotten to specify the SkookumScript type of this blueprint as '%s' in its SkookumScript component.", function_entry.m_sk_class_p->get_name_cstr(), function_entry.m_invokable_name.as_cstr(), this_p->get_class()->get_name_cstr(), function_entry.m_sk_class_p->get_name_cstr()));
      }
    else
  #endif
      {
      // Invoke the coroutine on this_p - might return immediately
      icoroutine_p->on_update();
      }

  // Free if not in use by our invoked coroutine
  this_p->dereference();
  }