//===-- ScriptedPythonInterface.h -------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLDB_SOURCE_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H
#define LLDB_SOURCE_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H

#include <optional>
#include <sstream>
#include <tuple>
#include <type_traits>
#include <utility>

#include "lldb/Interpreter/Interfaces/ScriptedInterface.h"
#include "lldb/Utility/DataBufferHeap.h"

#include "../PythonDataObjects.h"
#include "../SWIGPythonBridge.h"
#include "../ScriptInterpreterPythonImpl.h"

namespace lldb_private {
class ScriptInterpreterPythonImpl;
class ScriptedPythonInterface : virtual public ScriptedInterface {
public:
  ScriptedPythonInterface(ScriptInterpreterPythonImpl &interpreter);
  ~ScriptedPythonInterface() override = default;

  enum class AbstractMethodCheckerCases {
    eNotImplemented,
    eNotAllocated,
    eNotCallable,
    eUnknownArgumentCount,
    eInvalidArgumentCount,
    eValid
  };

  struct AbstractMethodCheckerPayload {

    struct InvalidArgumentCountPayload {
      InvalidArgumentCountPayload(size_t required, size_t actual)
          : required_argument_count(required), actual_argument_count(actual) {}

      size_t required_argument_count;
      size_t actual_argument_count;
    };

    AbstractMethodCheckerCases checker_case;
    std::variant<std::monostate, InvalidArgumentCountPayload> payload;
  };

  llvm::Expected<FileSpec> GetScriptedModulePath() override {
    using namespace python;
    using Locker = ScriptInterpreterPythonImpl::Locker;

    Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
                   Locker::FreeLock);

    if (!m_object_instance_sp)
      return llvm::createStringError("scripted Interface has invalid object");

    PythonObject py_obj =
        PythonObject(PyRefType::Borrowed,
                     static_cast<PyObject *>(m_object_instance_sp->GetValue()));

    if (!py_obj.IsAllocated())
      return llvm::createStringError(
          "scripted Interface has invalid python object");

    PythonObject py_obj_class = py_obj.GetAttributeValue("__class__");
    if (!py_obj_class.IsValid())
      return llvm::createStringError(
          "scripted Interface python object is missing '__class__' attribute");

    PythonObject py_obj_module = py_obj_class.GetAttributeValue("__module__");
    if (!py_obj_module.IsValid())
      return llvm::createStringError(
          "scripted Interface python object '__class__' is missing "
          "'__module__' attribute");

    PythonString py_obj_module_str = py_obj_module.Str();
    if (!py_obj_module_str.IsValid())
      return llvm::createStringError(
          "scripted Interface python object '__class__.__module__' attribute "
          "is not a string");

    llvm::StringRef py_obj_module_str_ref = py_obj_module_str.GetString();
    PythonModule py_module = PythonModule::AddModule(py_obj_module_str_ref);
    if (!py_module.IsValid())
      return llvm::createStringError("failed to import '%s' module",
                                     py_obj_module_str_ref.data());

    PythonObject py_module_file = py_module.GetAttributeValue("__file__");
    if (!py_module_file.IsValid())
      return llvm::createStringError(
          "module '%s' is missing '__file__' attribute",
          py_obj_module_str_ref.data());

    PythonString py_module_file_str = py_module_file.Str();
    if (!py_module_file_str.IsValid())
      return llvm::createStringError(
          "module '%s.__file__' attribute is not a string",
          py_obj_module_str_ref.data());

    return FileSpec(py_module_file_str.GetString());
  }

  llvm::Expected<std::map<llvm::StringLiteral, AbstractMethodCheckerPayload>>
  CheckAbstractMethodImplementation(
      const python::PythonDictionary &class_dict) const {

    using namespace python;

    std::map<llvm::StringLiteral, AbstractMethodCheckerPayload> checker;
#define SET_CASE_AND_CONTINUE(method_name, case)                               \
  {                                                                            \
    checker[method_name] = {case, {}};                                         \
    continue;                                                                  \
  }

    for (const AbstractMethodRequirement &requirement :
         GetAbstractMethodRequirements()) {
      llvm::StringLiteral method_name = requirement.name;
      if (!class_dict.HasKey(method_name))
        SET_CASE_AND_CONTINUE(method_name,
                              AbstractMethodCheckerCases::eNotImplemented)
      llvm::Expected<PythonObject> callable_or_err =
          class_dict.GetItem(method_name);
      if (!callable_or_err) {
        llvm::consumeError(callable_or_err.takeError());
        SET_CASE_AND_CONTINUE(method_name,
                              AbstractMethodCheckerCases::eNotAllocated)
      }

      PythonCallable callable = callable_or_err->AsType<PythonCallable>();
      if (!callable)
        SET_CASE_AND_CONTINUE(method_name,
                              AbstractMethodCheckerCases::eNotCallable)

      if (!requirement.min_arg_count)
        SET_CASE_AND_CONTINUE(method_name, AbstractMethodCheckerCases::eValid)

      auto arg_info_or_err = callable.GetArgInfo();
      if (!arg_info_or_err) {
        llvm::consumeError(arg_info_or_err.takeError());
        SET_CASE_AND_CONTINUE(method_name,
                              AbstractMethodCheckerCases::eUnknownArgumentCount)
      }

      PythonCallable::ArgInfo arg_info = *arg_info_or_err;
      if (requirement.min_arg_count <= arg_info.max_positional_args) {
        SET_CASE_AND_CONTINUE(method_name, AbstractMethodCheckerCases::eValid)
      } else {
        checker[method_name] = {
            AbstractMethodCheckerCases::eInvalidArgumentCount,
            AbstractMethodCheckerPayload::InvalidArgumentCountPayload(
                requirement.min_arg_count, arg_info.max_positional_args)};
      }
    }

#undef SET_CASE_AND_CONTINUE

    return checker;
  }

  template <typename... Args>
  llvm::Expected<StructuredData::GenericSP>
  CreatePluginObject(const ScriptedMetadata &scripted_metadata,
                     StructuredData::Generic *script_obj, Args... args) {
    using namespace python;
    using Locker = ScriptInterpreterPythonImpl::Locker;

    Log *log = GetLog(LLDBLog::Script);
    auto create_error = [](llvm::StringLiteral format, auto &&...ts) {
      return llvm::createStringError(
          llvm::formatv(format.data(), std::forward<decltype(ts)>(ts)...)
              .str());
    };

    m_scripted_metadata = scripted_metadata;
    llvm::StringRef class_name = scripted_metadata.GetClassName();
    bool has_class_name = !class_name.empty();
    bool has_interpreter_dict =
        !(llvm::StringRef(m_interpreter.GetDictionaryName()).empty());
    if (!has_class_name && !has_interpreter_dict && !script_obj) {
      if (!has_class_name)
        return create_error("Missing script class name.");
      else if (!has_interpreter_dict)
        return create_error("Invalid script interpreter dictionary.");
      else
        return create_error("Missing scripting object.");
    }

    Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
                   Locker::FreeLock);

    PythonObject result = {};

    if (script_obj) {
      result = PythonObject(PyRefType::Borrowed,
                            static_cast<PyObject *>(script_obj->GetValue()));
    } else {
      auto dict =
          PythonModule::MainModule().ResolveName<python::PythonDictionary>(
              m_interpreter.GetDictionaryName());
      if (!dict.IsAllocated())
        return create_error("Could not find interpreter dictionary: {0}",
                            m_interpreter.GetDictionaryName());

      auto init =
          PythonObject::ResolveNameWithDictionary<python::PythonCallable>(
              class_name, dict);
      if (!init.IsAllocated())
        return create_error("Could not find script class: {0}",
                            class_name.data());

      std::tuple<Args...> original_args = std::forward_as_tuple(args...);
      auto transformed_args = TransformArgs(original_args);

      std::string error_string;
      llvm::Expected<PythonCallable::ArgInfo> arg_info = init.GetArgInfo();
      if (!arg_info) {
        llvm::handleAllErrors(
            arg_info.takeError(),
            [&](PythonException &E) { error_string.append(E.ReadBacktrace()); },
            [&](const llvm::ErrorInfoBase &E) {
              error_string.append(E.message());
            });
        return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                       error_string);
      }

      llvm::Expected<PythonObject> expected_return_object =
          create_error("Resulting object is not initialized.");

      // This relax the requirement on the number of argument for
      // initializing scripting extension if the size of the interface
      // parameter pack contains 1 less element than the extension maximum
      // number of positional arguments for this initializer.
      //
      // This addresses the cases where the embedded interpreter session
      // dictionary is passed to the extension initializer which is not used
      // most of the time.
      // Note, though none of our API's suggest defining the interfaces with
      // varargs, we have some extant clients that were doing that.  To keep
      // from breaking them, we just say putting a varargs in these signatures
      // turns off argument checking.
      size_t num_args = sizeof...(Args);
      if (arg_info->max_positional_args != PythonCallable::ArgInfo::UNBOUNDED &&
          num_args != arg_info->max_positional_args) {
        if (num_args != arg_info->max_positional_args - 1)
          return create_error("Passed arguments ({0}) doesn't match the number "
                              "of expected arguments ({1}).",
                              num_args, arg_info->max_positional_args);

        std::apply(
            [&init, &expected_return_object](auto &&...args) {
              llvm::consumeError(expected_return_object.takeError());
              expected_return_object = init(args...);
            },
            std::tuple_cat(transformed_args, std::make_tuple(dict)));
      } else {
        std::apply(
            [&init, &expected_return_object](auto &&...args) {
              llvm::consumeError(expected_return_object.takeError());
              expected_return_object = init(args...);
            },
            transformed_args);
      }

      if (!expected_return_object)
        return expected_return_object.takeError();
      result = expected_return_object.get();
    }

    if (!result.IsValid())
      return create_error("Resulting object is not a valid Python Object.");
    if (!result.HasAttribute("__class__"))
      return create_error("Resulting object doesn't have '__class__' member.");

    PythonObject obj_class = result.GetAttributeValue("__class__");
    if (!obj_class.IsValid())
      return create_error("Resulting class object is not a valid.");
    if (!obj_class.HasAttribute("__name__"))
      return create_error(
          "Resulting object class doesn't have '__name__' member.");
    PythonString obj_class_name =
        obj_class.GetAttributeValue("__name__").AsType<PythonString>();

    PythonObject object_class_mapping_proxy =
        obj_class.GetAttributeValue("__dict__");
    if (!obj_class.HasAttribute("__dict__"))
      return create_error(
          "Resulting object class doesn't have '__dict__' member.");

    PythonCallable dict_converter = PythonModule::BuiltinsModule()
                                        .ResolveName("dict")
                                        .AsType<PythonCallable>();
    if (!dict_converter.IsAllocated())
      return create_error(
          "Python 'builtins' module doesn't have 'dict' class.");

    PythonDictionary object_class_dict =
        dict_converter(object_class_mapping_proxy).AsType<PythonDictionary>();
    if (!object_class_dict.IsAllocated())
      return create_error("Coudn't create dictionary from resulting object "
                          "class mapping proxy object.");

    auto checker_or_err = CheckAbstractMethodImplementation(object_class_dict);
    if (!checker_or_err)
      return checker_or_err.takeError();

    llvm::Error abstract_method_errors = llvm::Error::success();
    for (const auto &method_checker : *checker_or_err)
      switch (method_checker.second.checker_case) {
      case AbstractMethodCheckerCases::eNotImplemented:
        abstract_method_errors = llvm::joinErrors(
            std::move(abstract_method_errors),
            std::move(create_error("Abstract method {0}.{1} not implemented.",
                                   obj_class_name.GetString(),
                                   method_checker.first)));
        break;
      case AbstractMethodCheckerCases::eNotAllocated:
        abstract_method_errors = llvm::joinErrors(
            std::move(abstract_method_errors),
            std::move(create_error("Abstract method {0}.{1} not allocated.",
                                   obj_class_name.GetString(),
                                   method_checker.first)));
        break;
      case AbstractMethodCheckerCases::eNotCallable:
        abstract_method_errors = llvm::joinErrors(
            std::move(abstract_method_errors),
            std::move(create_error("Abstract method {0}.{1} not callable.",
                                   obj_class_name.GetString(),
                                   method_checker.first)));
        break;
      case AbstractMethodCheckerCases::eUnknownArgumentCount:
        abstract_method_errors = llvm::joinErrors(
            std::move(abstract_method_errors),
            std::move(create_error(
                "Abstract method {0}.{1} has unknown argument count.",
                obj_class_name.GetString(), method_checker.first)));
        break;
      case AbstractMethodCheckerCases::eInvalidArgumentCount: {
        auto &payload_variant = method_checker.second.payload;
        if (!std::holds_alternative<
                AbstractMethodCheckerPayload::InvalidArgumentCountPayload>(
                payload_variant)) {
          abstract_method_errors = llvm::joinErrors(
              std::move(abstract_method_errors),
              std::move(create_error(
                  "Abstract method {0}.{1} has unexpected argument count.",
                  obj_class_name.GetString(), method_checker.first)));
        } else {
          auto payload = std::get<
              AbstractMethodCheckerPayload::InvalidArgumentCountPayload>(
              payload_variant);
          abstract_method_errors = llvm::joinErrors(
              std::move(abstract_method_errors),
              std::move(
                  create_error("Abstract method {0}.{1} has unexpected "
                               "argument count (expected {2} but has {3}).",
                               obj_class_name.GetString(), method_checker.first,
                               payload.required_argument_count,
                               payload.actual_argument_count)));
        }
      } break;
      case AbstractMethodCheckerCases::eValid:
        LLDB_LOG(log, "Abstract method {0}.{1} implemented & valid.",
                 obj_class_name.GetString(), method_checker.first);
        break;
      }

    if (abstract_method_errors) {
      Status error = Status::FromError(std::move(abstract_method_errors));
      LLDB_LOG(log, "Abstract method error in {0}:\n{1}", class_name,
               error.AsCString());
      return error.ToError();
    }

    m_object_instance_sp = StructuredData::GenericSP(
        new StructuredPythonObject(std::move(result)));
    return m_object_instance_sp;
  }

  /// Call a static method on a Python class without creating an instance.
  ///
  /// This method resolves a Python class by name and calls a static method
  /// on it, returning the result. This is useful for calling class-level
  /// methods that don't require an instance.
  ///
  /// \param class_name The fully-qualified name of the Python class.
  /// \param method_name The name of the static method to call.
  /// \param error Output parameter to receive error information if the call
  /// fails.
  /// \param args Arguments to pass to the static method.
  ///
  /// \return The return value of the static method call, or an error value.
  template <typename T = StructuredData::ObjectSP, typename... Args>
  T CallStaticMethod(llvm::StringRef class_name, llvm::StringRef method_name,
                     Status &error, Args &&...args) {
    using namespace python;
    using Locker = ScriptInterpreterPythonImpl::Locker;

    std::string caller_signature =
        llvm::Twine(LLVM_PRETTY_FUNCTION + llvm::Twine(" (") +
                    llvm::Twine(class_name) + llvm::Twine(".") +
                    llvm::Twine(method_name) + llvm::Twine(")"))
            .str();

    if (class_name.empty())
      return ErrorWithMessage<T>(caller_signature, "missing script class name",
                                 error);

    Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
                   Locker::FreeLock);

    // Get the interpreter dictionary.
    auto dict =
        PythonModule::MainModule().ResolveName<python::PythonDictionary>(
            m_interpreter.GetDictionaryName());
    if (!dict.IsAllocated())
      return ErrorWithMessage<T>(
          caller_signature,
          llvm::formatv("could not find interpreter dictionary: {0}",
                        m_interpreter.GetDictionaryName())
              .str(),
          error);

    // Resolve the class.
    auto class_obj =
        PythonObject::ResolveNameWithDictionary<python::PythonCallable>(
            class_name, dict);
    if (!class_obj.IsAllocated())
      return ErrorWithMessage<T>(
          caller_signature,
          llvm::formatv("could not find script class: {0}", class_name).str(),
          error);

    // Get the static method from the class.
    if (!class_obj.HasAttribute(method_name))
      return ErrorWithMessage<T>(
          caller_signature,
          llvm::formatv("class {0} does not have method {1}", class_name,
                        method_name)
              .str(),
          error);

    PythonCallable method =
        class_obj.GetAttributeValue(method_name).AsType<PythonCallable>();
    if (!method.IsAllocated())
      return ErrorWithMessage<T>(caller_signature,
                                 llvm::formatv("method {0}.{1} is not callable",
                                               class_name, method_name)
                                     .str(),
                                 error);

    // Transform the arguments.
    std::tuple<Args...> original_args = std::forward_as_tuple(args...);
    auto transformed_args = TransformArgs(original_args);

    // Call the static method.
    llvm::Expected<PythonObject> expected_return_object =
        llvm::createStringError("not initialized");
    std::apply(
        [&method, &expected_return_object](auto &&...args) {
          llvm::consumeError(expected_return_object.takeError());
          expected_return_object = method(args...);
        },
        transformed_args);

    if (llvm::Error e = expected_return_object.takeError()) {
      error = Status::FromError(std::move(e));
      return ErrorWithMessage<T>(
          caller_signature, "python static method could not be called", error);
    }

    PythonObject py_return = std::move(expected_return_object.get());

    // Re-assign reference and pointer arguments if needed.
    if (sizeof...(Args) > 0)
      if (!ReassignPtrsOrRefsArgs(original_args, transformed_args))
        return ErrorWithMessage<T>(
            caller_signature,
            "couldn't re-assign reference and pointer arguments", error);

    // Extract value from Python object (handles unallocated case).
    return ExtractValueFromPythonObject<T>(py_return, error);
  }

protected:
  template <typename T = StructuredData::ObjectSP>
  T ExtractValueFromPythonObject(python::PythonObject &p, Status &error) {
    return p.CreateStructuredObject();
  }

  template <typename T = StructuredData::ObjectSP, typename... Args>
  T Dispatch(llvm::StringRef method_name, Status &error, Args &&...args) {
    using namespace python;
    using Locker = ScriptInterpreterPythonImpl::Locker;

    std::string caller_signature =
        llvm::Twine(LLVM_PRETTY_FUNCTION + llvm::Twine(" (") +
                    llvm::Twine(method_name) + llvm::Twine(")"))
            .str();
    if (!m_object_instance_sp)
      return ErrorWithMessage<T>(caller_signature, "python object ill-formed",
                                 error);

    Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
                   Locker::FreeLock);

    PythonObject implementor(PyRefType::Borrowed,
                             (PyObject *)m_object_instance_sp->GetValue());

    if (!implementor.IsAllocated())
      return llvm::is_contained(GetAbstractMethods(), method_name)
                 ? ErrorWithMessage<T>(caller_signature,
                                       "python implementor not allocated",
                                       error)
                 : T{};

    std::tuple<Args...> original_args = std::forward_as_tuple(args...);
    auto transformed_args = TransformArgs(original_args);

    llvm::Expected<PythonObject> expected_return_object =
        llvm::createStringError("not initialized");
    std::apply(
        [&implementor, &method_name, &expected_return_object](auto &&...args) {
          llvm::consumeError(expected_return_object.takeError());
          expected_return_object =
              implementor.CallMethod(method_name.data(), args...);
        },
        transformed_args);

    if (llvm::Error e = expected_return_object.takeError()) {
      error = Status::FromError(std::move(e));
      return ErrorWithMessage<T>(caller_signature,
                                 "python method could not be called", error);
    }

    PythonObject py_return = std::move(expected_return_object.get());

    // Now that we called the python method with the transformed arguments,
    // we need to iterate again over both the original and transformed
    // parameter pack, and transform back the parameter that were passed in
    // the original parameter pack as references or pointers.
    if (sizeof...(Args) > 0)
      if (!ReassignPtrsOrRefsArgs(original_args, transformed_args))
        return ErrorWithMessage<T>(
            caller_signature,
            "couldn't re-assign reference and pointer arguments", error);

    if (!py_return.IsAllocated())
      return {};
    return ExtractValueFromPythonObject<T>(py_return, error);
  }

  template <typename... Args>
  Status GetStatusFromMethod(llvm::StringRef method_name, Args &&...args) {
    Status error;
    Dispatch<Status>(method_name, error, std::forward<Args>(args)...);

    return error;
  }

  template <typename T> T Transform(T object) {
    // No Transformation for generic usage
    return {object};
  }

  python::PythonObject Transform(bool arg) {
    // Boolean arguments need to be turned into python objects.
    return python::PythonBoolean(arg);
  }

  python::PythonObject Transform(const Status &arg) {
    return python::SWIGBridge::ToSWIGWrapper(arg.Clone());
  }

  python::PythonObject Transform(Status &&arg) {
    return python::SWIGBridge::ToSWIGWrapper(std::move(arg));
  }

  python::PythonObject Transform(const StructuredDataImpl &arg) {
    return python::SWIGBridge::ToSWIGWrapper(arg);
  }

  template <typename T, typename = std::enable_if_t<
                            std::is_base_of_v<StructuredData::Object, T>>>
  python::PythonObject Transform(std::shared_ptr<T> arg) {
    return Transform(StructuredDataImpl(arg));
  }

  python::PythonObject Transform(lldb::ExecutionContextRefSP arg) {
    return python::SWIGBridge::ToSWIGWrapper(arg);
  }

  python::PythonObject Transform(lldb::TargetSP arg) {
    return python::SWIGBridge::ToSWIGWrapper(arg);
  }

  python::PythonObject Transform(lldb::BreakpointSP arg) {
    return python::SWIGBridge::ToSWIGWrapper(arg);
  }

  python::PythonObject Transform(lldb::BreakpointLocationSP arg) {
    return python::SWIGBridge::ToSWIGWrapper(arg);
  }

  python::PythonObject Transform(lldb::ProcessSP arg) {
    return python::SWIGBridge::ToSWIGWrapper(arg);
  }

  python::PythonObject Transform(lldb::ThreadSP arg) {
    return python::SWIGBridge::ToSWIGWrapper(arg);
  }

  python::PythonObject Transform(lldb::StackFrameListSP arg) {
    return python::SWIGBridge::ToSWIGWrapper(arg);
  }

  python::PythonObject Transform(lldb::ThreadPlanSP arg) {
    return python::SWIGBridge::ToSWIGWrapper(arg);
  }

  python::PythonObject Transform(lldb::ProcessAttachInfoSP arg) {
    return python::SWIGBridge::ToSWIGWrapper(arg);
  }

  python::PythonObject Transform(lldb::ProcessLaunchInfoSP arg) {
    return python::SWIGBridge::ToSWIGWrapper(arg);
  }

  python::PythonObject Transform(Event *arg) {
    return python::SWIGBridge::ToSWIGWrapper(arg);
  }

  python::PythonObject Transform(const SymbolContext &arg) {
    return python::SWIGBridge::ToSWIGWrapper(arg);
  }

  python::PythonObject Transform(lldb::StreamSP arg) {
    return python::SWIGBridge::ToSWIGWrapper(arg.get());
  }

  python::PythonObject Transform(lldb::StackFrameSP arg) {
    return python::SWIGBridge::ToSWIGWrapper(arg);
  }

  python::PythonObject Transform(lldb::DataExtractorSP arg) {
    return python::SWIGBridge::ToSWIGWrapper(arg);
  }

  python::PythonObject Transform(lldb::DescriptionLevel arg) {
    return python::SWIGBridge::ToSWIGWrapper(arg);
  }

  python::PythonObject Transform(lldb::ValueObjectSP arg) {
    return python::SWIGBridge::ToSWIGWrapper(arg);
  }

  template <typename T, typename U>
  void ReverseTransform(T &original_arg, U transformed_arg, Status &error) {
    // If U is not a PythonObject, don't touch it!
  }

  template <typename T>
  void ReverseTransform(T &original_arg, python::PythonObject transformed_arg,
                        Status &error) {
    original_arg = ExtractValueFromPythonObject<T>(transformed_arg, error);
  }

  void ReverseTransform(bool &original_arg,
                        python::PythonObject transformed_arg, Status &error) {
    python::PythonBoolean boolean_arg = python::PythonBoolean(
        python::PyRefType::Borrowed, transformed_arg.get());
    if (boolean_arg.IsValid())
      original_arg = boolean_arg.GetValue();
    else
      error = Status::FromErrorStringWithFormatv(
          "{}: Invalid boolean argument.", LLVM_PRETTY_FUNCTION);
  }

  template <std::size_t... I, typename... Args>
  auto TransformTuple(const std::tuple<Args...> &args,
                      std::index_sequence<I...>) {
    return std::make_tuple(Transform(std::get<I>(args))...);
  }

  // This will iterate over the Dispatch parameter pack and replace in-place
  // every `lldb_private` argument that has a SB counterpart.
  template <typename... Args>
  auto TransformArgs(const std::tuple<Args...> &args) {
    return TransformTuple(args, std::make_index_sequence<sizeof...(Args)>());
  }

  template <typename T, typename U>
  void TransformBack(T &original_arg, U transformed_arg, Status &error) {
    ReverseTransform(original_arg, transformed_arg, error);
  }

  template <std::size_t... I, typename... Ts, typename... Us>
  bool ReassignPtrsOrRefsArgs(std::tuple<Ts...> &original_args,
                              std::tuple<Us...> &transformed_args,
                              std::index_sequence<I...>) {
    Status error;
    (TransformBack(std::get<I>(original_args), std::get<I>(transformed_args),
                   error),
     ...);
    return error.Success();
  }

  template <typename... Ts, typename... Us>
  bool ReassignPtrsOrRefsArgs(std::tuple<Ts...> &original_args,
                              std::tuple<Us...> &transformed_args) {
    if (sizeof...(Ts) != sizeof...(Us))
      return false;

    return ReassignPtrsOrRefsArgs(original_args, transformed_args,
                                  std::make_index_sequence<sizeof...(Ts)>());
  }

  template <typename T, typename... Args>
  void FormatArgs(std::string &fmt, T arg, Args... args) const {
    FormatArgs(fmt, arg);
    FormatArgs(fmt, args...);
  }

  template <typename T> void FormatArgs(std::string &fmt, T arg) const {
    fmt += python::PythonFormat<T>::format;
  }

  void FormatArgs(std::string &fmt) const {}

  // The lifetime is managed by the ScriptInterpreter
  ScriptInterpreterPythonImpl &m_interpreter;
};

template <>
StructuredData::ArraySP
ScriptedPythonInterface::ExtractValueFromPythonObject<StructuredData::ArraySP>(
    python::PythonObject &p, Status &error);

template <>
StructuredData::DictionarySP
ScriptedPythonInterface::ExtractValueFromPythonObject<
    StructuredData::DictionarySP>(python::PythonObject &p, Status &error);

template <>
Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>(
    python::PythonObject &p, Status &error);

template <>
Event *ScriptedPythonInterface::ExtractValueFromPythonObject<Event *>(
    python::PythonObject &p, Status &error);

template <>
SymbolContext
ScriptedPythonInterface::ExtractValueFromPythonObject<SymbolContext>(
    python::PythonObject &p, Status &error);

template <>
lldb::StreamSP
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StreamSP>(
    python::PythonObject &p, Status &error);

template <>
lldb::ThreadSP
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::ThreadSP>(
    python::PythonObject &p, Status &error);

template <>
lldb::StackFrameSP
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StackFrameSP>(
    python::PythonObject &p, Status &error);

template <>
lldb::BreakpointSP
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::BreakpointSP>(
    python::PythonObject &p, Status &error);

template <>
lldb::BreakpointLocationSP
ScriptedPythonInterface::ExtractValueFromPythonObject<
    lldb::BreakpointLocationSP>(python::PythonObject &p, Status &error);

template <>
lldb::ProcessAttachInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject<
    lldb::ProcessAttachInfoSP>(python::PythonObject &p, Status &error);

template <>
lldb::ProcessLaunchInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject<
    lldb::ProcessLaunchInfoSP>(python::PythonObject &p, Status &error);

template <>
lldb::DataExtractorSP
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>(
    python::PythonObject &p, Status &error);

template <>
std::optional<MemoryRegionInfo>
ScriptedPythonInterface::ExtractValueFromPythonObject<
    std::optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error);

template <>
lldb::ExecutionContextRefSP
ScriptedPythonInterface::ExtractValueFromPythonObject<
    lldb::ExecutionContextRefSP>(python::PythonObject &p, Status &error);

template <>
lldb::DescriptionLevel
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DescriptionLevel>(
    python::PythonObject &p, Status &error);

template <>
lldb::StackFrameListSP
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StackFrameListSP>(
    python::PythonObject &p, Status &error);

template <>
lldb::ValueObjectSP
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::ValueObjectSP>(
    python::PythonObject &p, Status &error);

template <>
lldb::TargetSP
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::TargetSP>(
    python::PythonObject &p, Status &error);

template <>
lldb::ValueObjectListSP
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::ValueObjectListSP>(
    python::PythonObject &p, Status &error);

template <>
std::optional<lldb::ValueType>
ScriptedPythonInterface::ExtractValueFromPythonObject<
    std::optional<lldb::ValueType>>(python::PythonObject &p, Status &error);

} // namespace lldb_private

#endif // LLDB_SOURCE_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H
