//===-- 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/API/SBCommandReturnObject.h"
#include "lldb/Interpreter/Interfaces/ScriptedInterface.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Policy.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, std::string>
        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");

    return GetModuleFile(py_obj_module_str.GetString());
  }

  /// The file the already imported \p module_name was loaded from, read from
  /// its `__file__`. The caller must hold the GIL.
  static llvm::Expected<FileSpec> GetModuleFile(llvm::StringRef module_name) {
    using namespace python;

    PythonModule py_module = PythonModule::AddModule(module_name);
    if (!py_module.IsValid())
      return llvm::createStringError(
          llvm::formatv("failed to import '{0}' module", module_name).str());

    PythonObject py_module_file = py_module.GetAttributeValue("__file__");
    if (!py_module_file.IsValid())
      return llvm::createStringError(
          llvm::formatv("module '{0}' is missing '__file__' attribute",
                        module_name)
              .str());

    PythonString py_module_file_str = py_module_file.Str();
    if (!py_module_file_str.IsValid())
      return llvm::createStringError(
          llvm::formatv("module '{0}.__file__' attribute is not a string",
                        module_name)
              .str());

    return FileSpec(py_module_file_str.GetString());
  }

  llvm::Expected<std::map<llvm::StringLiteral, AbstractMethodCheckerPayload>>
  CheckAbstractMethodImplementation(
      const python::PythonObject &obj_class) 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;
      // Look up via attribute access so inherited methods are found; the
      // class's own __dict__ omits anything defined on a base class.
      if (!obj_class.HasAttribute(method_name))
        SET_CASE_AND_CONTINUE(method_name,
                              AbstractMethodCheckerCases::eNotImplemented)
      PythonObject attr = obj_class.GetAttributeValue(method_name);
      if (!attr.IsAllocated())
        SET_CASE_AND_CONTINUE(method_name,
                              AbstractMethodCheckerCases::eNotAllocated)

      PythonCallable callable = attr.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) {
        checker[method_name] = {
            AbstractMethodCheckerCases::eUnknownArgumentCount,
            ExtractPythonError(arg_info_or_err.takeError())};
        continue;
      }

      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;
  }

  /// Diagnose every abstract-method violation on \a obj_class at once.
  ///
  /// \a obj_class is a class object, whether resolved by name or taken from an
  /// instance's `__class__`. Resolving it by name means this can run before any
  /// instance exists (see CreatePluginObject), which uses it to reject a
  /// malformed class without executing its `__init__`.
  llvm::Error CheckAbstractMethods(const python::PythonObject &obj_class,
                                   llvm::StringRef qualified_class_name) const {
    Log *log = GetLog(LLDBLog::Script);

    // Per-method diagnostics name the class the way Python does, unqualified.
    python::PythonString obj_class_name =
        obj_class.GetAttributeValue("__name__").AsType<python::PythonString>();
    llvm::StringRef class_name = obj_class_name.IsValid()
                                     ? obj_class_name.GetString()
                                     : qualified_class_name;
    auto create_error = [](llvm::StringLiteral format, auto &&...ts) {
      return llvm::createStringError(
          llvm::formatv(format.data(), std::forward<decltype(ts)>(ts)...)
              .str());
    };

    auto checker_or_err = CheckAbstractMethodImplementation(obj_class);
    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),
            create_error("abstract method {0}.{1} not implemented", class_name,
                         method_checker.first));
        break;
      case AbstractMethodCheckerCases::eNotAllocated:
        abstract_method_errors = llvm::joinErrors(
            std::move(abstract_method_errors),
            create_error("abstract method {0}.{1} not allocated", class_name,
                         method_checker.first));
        break;
      case AbstractMethodCheckerCases::eNotCallable:
        abstract_method_errors = llvm::joinErrors(
            std::move(abstract_method_errors),
            create_error("abstract method {0}.{1} not callable", class_name,
                         method_checker.first));
        break;
      case AbstractMethodCheckerCases::eUnknownArgumentCount: {
        const std::string *py_error =
            std::get_if<std::string>(&method_checker.second.payload);
        abstract_method_errors = llvm::joinErrors(
            std::move(abstract_method_errors),
            create_error(
                "abstract method {0}.{1} has unknown argument count: {2}",
                class_name, method_checker.first,
                py_error ? *py_error : "<no further information>"));
      } 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),
              create_error(
                  "abstract method {0}.{1} has unexpected argument count",
                  class_name, method_checker.first));
        } else {
          auto payload = std::get<
              AbstractMethodCheckerPayload::InvalidArgumentCountPayload>(
              payload_variant);
          abstract_method_errors = llvm::joinErrors(
              std::move(abstract_method_errors),
              create_error("abstract method {0}.{1} has unexpected "
                           "argument count (expected {2} but has {3})",
                           class_name, method_checker.first,
                           payload.required_argument_count,
                           payload.actual_argument_count));
        }
      } break;
      case AbstractMethodCheckerCases::eValid:
        LLDB_LOG(log, "Abstract method {0}.{1} implemented & valid.",
                 class_name, 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}", qualified_class_name,
               error.AsCString());
      return error.ToError();
    }

    return llvm::Error::success();
  }

  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;

    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");
    }

    std::optional<PolicyStack::Guard> policy_guard;
    if (!UserCanRunDirectly())
      policy_guard = PolicyStack::Get().PushScriptedExtensionCall();

    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);
      }

      if (llvm::Error error = CheckAbstractMethods(init, class_name))
        return std::move(error);

      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) {
          // `expected_return_object` starts in an error state; consume it
          // before we return with a different error, or its destructor
          // will abort.
          llvm::consumeError(expected_return_object.takeError());
          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) {
              if (!expected_return_object)
                llvm::consumeError(expected_return_object.takeError());
              expected_return_object = init.Call(args...);
            },
            std::tuple_cat(transformed_args, std::make_tuple(dict)));
      } else {
        std::apply(
            [&init, &expected_return_object](auto &&...args) {
              if (!expected_return_object)
                llvm::consumeError(expected_return_object.takeError());
              expected_return_object = init.Call(args...);
            },
            transformed_args);
      }

      if (!expected_return_object)
        // Drain the Python exception into a plain string while the GIL is
        // still held: `PythonException` owns raw `PyObject*` references, and
        // `py_lock` (and the GIL it holds) is released as this function
        // returns, before the caller gets a chance to touch the error.
        return llvm::createStringError(
            ExtractPythonError(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>();

    // We were handed an instance rather than building one, so there was no
    // constructor to run the check ahead of; validate it now.
    if (script_obj)
      if (llvm::Error error =
              CheckAbstractMethods(obj_class, obj_class_name.GetString()))
        return std::move(error);

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

    // An object handed over by the script wasn't built from the metadata,
    // which may even describe its creator, so name it after its own class and
    // don't attribute the metadata's arguments to it.
    std::string qualified_class_name = script_obj ? "" : class_name.str();
    PythonString obj_module_name =
        obj_class.GetAttributeValue("__module__").AsType<PythonString>();
    if (qualified_class_name.empty() && obj_module_name.IsValid())
      qualified_class_name =
          llvm::formatv("{0}.{1}", obj_module_name.GetString(),
                        obj_class_name.GetString())
              .str();

    // Modules can be imported or reloaded without LLDB seeing it, so ask the
    // class's module for its current file rather than remembering one.
    FileSpec source_path;
    if (obj_module_name.IsValid()) {
      if (llvm::Expected<FileSpec> path_or_err =
              GetModuleFile(obj_module_name.GetString()))
        source_path = *path_or_err;
      else
        LLDB_LOG_ERROR(GetLog(LLDBLog::Script), path_or_err.takeError(),
                       "failed to find the file defining {1}: {0}",
                       qualified_class_name);
    }
    if (!script_obj)
      m_scripted_metadata->SetSourcePath(source_path);
    RegisterInstance(m_interpreter.GetScriptedInstanceRegistry(),
                     std::move(qualified_class_name), std::move(source_path),
                     script_obj ? nullptr : m_scripted_metadata->GetArgsSP());

    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 args Arguments to pass to the static method.
  ///
  /// \return The return value of the static method call, or an error.
  template <typename T = StructuredData::ObjectSP, typename... Args>
  llvm::Expected<T> CallStaticMethod(llvm::StringRef class_name,
                                     llvm::StringRef method_name,
                                     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 LogAndError(caller_signature, "missing script class name");

    std::optional<PolicyStack::Guard> policy_guard;
    if (!UserCanRunDirectly())
      policy_guard = PolicyStack::Get().PushScriptedExtensionCall();

    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 LogAndError(caller_signature,
                         "could not find interpreter dictionary: {0}",
                         m_interpreter.GetDictionaryName());

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

    // Get the static method from the class.
    if (!class_obj.HasAttribute(method_name))
      return llvm::make_error<UnimplementedError>(
          llvm::formatv("{0}.{1}", class_name, method_name).str());

    PythonCallable method =
        class_obj.GetAttributeValue(method_name).AsType<PythonCallable>();
    if (!method.IsAllocated())
      return LogAndError(caller_signature, "method {0}.{1} is not callable",
                         class_name, method_name);

    // 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) {
          if (!expected_return_object)
            llvm::consumeError(expected_return_object.takeError());
          expected_return_object = method.Call(args...);
        },
        transformed_args);

    if (llvm::Error e = expected_return_object.takeError()) {
      // TODO: Stringify `args` and include them in the message so users
      // can see what was passed to the failing call (e.g.
      // `read_memory_at_address(0x500000000, 4)`). Requires a SFINAE
      // helper that falls back to a placeholder for types without a
      // format_provider / operator<<.
      return LogAndError(
          caller_signature, "python exception in {0} method '{1}': {2}",
          class_name, method_name, ExtractPythonError(std::move(e)));
    }

    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 LogAndError(
            caller_signature,
            "couldn't re-assign reference and pointer arguments");

    // Extract value from Python object (handles unallocated case).
    if (!py_return.IsAllocated())
      return T{};
    return ExtractValueFromPythonObject<T>(py_return);
  }

protected:
  /// Extract detailed error message including Python backtrace if available.
  ///
  /// This helper processes llvm::Error objects that may contain PythonException
  /// instances, extracting full Python backtraces when available.
  ///
  /// \param error The llvm::Error to extract information from.
  /// \return A string containing the error message, including full Python
  ///         backtrace if the error was a PythonException.
  static std::string ExtractPythonError(llvm::Error error) {
    std::string error_msg;
    llvm::handleAllErrors(
        std::move(error),
        [&](python::PythonException &E) { error_msg = E.ReadBacktrace(); },
        [&](const llvm::ErrorInfoBase &E) { error_msg = E.message(); });
    return error_msg;
  }

  /// Log \a message against \a caller_name and return it as an error.
  ///
  /// The `Expected`-returning counterpart of
  /// `ScriptedInterface::ErrorWithMessage`: it reports the failure instead of
  /// folding it into a default-constructed value.
  template <typename... Ts>
  static llvm::Error LogAndError(llvm::StringRef caller_name,
                                 const char *format, Ts &&...ts) {
    std::string message = llvm::formatv(format, std::forward<Ts>(ts)...).str();
    LLDB_LOGF(GetLog(LLDBLog::Script), "%s ERROR = %s", caller_name.data(),
              message.c_str());
    return llvm::createStringError(message);
  }

  /// Log the failure in \a value_or_err and fall back to a default-constructed
  /// \c T.
  ///
  /// For entry points whose return type cannot express failure. Prefer
  /// propagating the error wherever the signature can carry it; this is the
  /// stop-gap, and it is at least strictly better than dropping the error.
  ///
  /// Logs any failure, an unimplemented method included: a site that dispatches
  /// with Dispatch() rather than DispatchToOptional() is asserting the method
  /// should have been there.
  template <typename T>
  static T LogAndDefault(llvm::Expected<T> value_or_err,
                         llvm::StringRef caller) {
    if (value_or_err)
      return std::move(*value_or_err);

    // Consume the error before logging: LLDB_LOGF doesn't evaluate its
    // arguments when the channel is disabled, which would leave the error
    // unchecked and abort.
    std::string message = llvm::toString(value_or_err.takeError());
    LLDB_LOGF(GetLog(LLDBLog::Script), "%s failed: %s", caller.str().c_str(),
              message.c_str());
    return T{};
  }

  /// Call an optional \a method_name, reporting "the script doesn't implement
  /// it" as \c std::nullopt rather than as a failure.
  ///
  /// Use this for callbacks a script may legitimately leave out. Any other
  /// failure - in particular an exception raised inside the method -
  /// propagates; this never papers over a method that ran and failed.
  template <typename T = StructuredData::ObjectSP, typename... Args>
  llvm::Expected<std::optional<T>>
  DispatchToOptional(llvm::StringRef method_name, Args &&...args) {
    if (!llvm::is_contained(GetOptionalMethods(), method_name))
      return LogAndError(
          LLVM_PRETTY_FUNCTION,
          "method '{0}' is not declared optional: list it in "
          "GetOptionalMethods(), or dispatch it with Dispatch(), "
          "where a missing method is an error",
          method_name);

    llvm::Expected<T> value_or_err =
        Dispatch<T>(method_name, std::forward<Args>(args)...);
    if (value_or_err)
      return std::move(*value_or_err);

    if (value_or_err.template errorIsA<UnimplementedError>()) {
      llvm::consumeError(value_or_err.takeError());
      return std::nullopt;
    }
    return value_or_err.takeError();
  }

  template <typename T = StructuredData::ObjectSP>
  llvm::Expected<T> ExtractValueFromPythonObject(python::PythonObject &p) {
    return p.CreateStructuredObject();
  }

  /// Call \a method_name on the scripted object.
  ///
  /// The returned \c Expected separates the two outcomes that a plain return
  /// value cannot: a successfully extracted value (which may legitimately be
  /// empty or null, e.g. when the Python method returns \c None) and a
  /// failure to call the method at all.
  ///
  /// A class that simply doesn't implement \a method_name fails with an
  /// \c UnimplementedError, so callers of optional callbacks can recognize
  /// and ignore that case without also swallowing real exceptions.
  template <typename T = StructuredData::ObjectSP, typename... Args>
  llvm::Expected<T> Dispatch(llvm::StringRef method_name, 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 LogAndError(caller_signature, "python object ill-formed");

    std::optional<PolicyStack::Guard> policy_guard;
    if (!UserCanRunDirectly())
      policy_guard = PolicyStack::Get().PushScriptedExtensionCall();

    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 LogAndError(caller_signature, "python implementor not allocated");

    PythonObject py_method = implementor.GetAttributeValue(method_name);
    if (!py_method.IsAllocated())
      return llvm::make_error<UnimplementedError>(
          llvm::formatv("{0}.{1}",
                        GetScriptedMetadata()
                            ? GetScriptedMetadata()->GetClassName()
                            : "<unknown>",
                        method_name)
              .str());

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

    // Trim trailing args if the Python method accepts fewer positional
    // parameters than we're passing (e.g. `num_children(self)` vs.
    // `num_children(self, max_count)`).
    size_t call_arity = sizeof...(Args);
    if (PythonCallable callable = py_method.AsType<PythonCallable>();
        callable.IsAllocated()) {
      if (llvm::Expected<PythonCallable::ArgInfo> arg_info =
              callable.GetArgInfo()) {
        if (arg_info->max_positional_args !=
                PythonCallable::ArgInfo::UNBOUNDED &&
            arg_info->max_positional_args < call_arity)
          call_arity = arg_info->max_positional_args;
      } else {
        llvm::consumeError(arg_info.takeError());
      }
    }

    llvm::Expected<PythonObject> expected_return_object =
        llvm::createStringError("not initialized");
    CallWithArity(call_arity, transformed_args,
                  std::make_index_sequence<sizeof...(Args) + 1>{},
                  [&implementor, &method_name,
                   &expected_return_object](auto &&...call_args) {
                    if (!expected_return_object)
                      llvm::consumeError(expected_return_object.takeError());
                    expected_return_object = implementor.CallMethod(
                        method_name.data(), call_args...);
                  });

    if (llvm::Error e = expected_return_object.takeError()) {
      // TODO: Stringify `args` and include them in the message so users
      // can see what was passed to the failing call (e.g.
      // `read_memory_at_address(0x500000000, 4)`). Requires a SFINAE
      // helper that falls back to a placeholder for types without a
      // format_provider / operator<<.
      //
      // Drain the Python exception into a plain string while the GIL is
      // still held: `PythonException` owns raw `PyObject*` references, and
      // `py_lock` is released as this function returns.
      return LogAndError(
          caller_signature, "python exception in {0} method '{1}': {2}",
          GetScriptedMetadata() ? GetScriptedMetadata()->GetClassName()
                                : "<unknown>",
          method_name, ExtractPythonError(std::move(e)));
    }

    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 LogAndError(
            caller_signature,
            "couldn't re-assign reference and pointer arguments");

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

  /// Call \a method_name and fold both failure channels into one `Status`:
  /// a failure to call the method at all, and the `SBError` the method
  /// returned. The latter used to be dropped on the floor.
  template <typename... Args>
  Status GetStatusFromMethod(llvm::StringRef method_name, Args &&...args) {
    llvm::Expected<Status> status_or_err =
        Dispatch<Status>(method_name, std::forward<Args>(args)...);
    if (!status_or_err)
      return Status::FromError(status_or_err.takeError());

    return std::move(*status_or_err);
  }

  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::StepType arg) {
    return python::SWIGBridge::ToSWIGWrapper(arg);
  }

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

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

  python::PythonObject Transform(const std::vector<std::string> &arg) {
    python::PythonList list(python::PyInitialValue::Empty);
    for (const std::string &s : arg)
      list.AppendItem(python::PythonString(s));
    return list;
  }

  python::ScopedPythonObject<lldb::SBCommandReturnObject>
  Transform(CommandReturnObject *arg) {
    return python::SWIGBridge::ToSWIGWrapper(*arg);
  }

  python::PythonObject Transform(const TypeSummaryOptions &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) {
    llvm::Expected<T> value_or_err =
        ExtractValueFromPythonObject<T>(transformed_arg);
    if (!value_or_err) {
      error = Status::FromError(value_or_err.takeError());
      return;
    }
    original_arg = std::move(*value_or_err);
  }

  // Read-only arguments (passed as `const T&`) have nothing to write back:
  // there's no `T` value to reassign into a const reference, and no
  // `ExtractValueFromPythonObject<T>` specialization should be required just
  // to satisfy this round-trip for a value the callee never mutates.
  template <typename T>
  void ReverseTransform(const T &original_arg,
                        python::PythonObject transformed_arg, Status &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)>());
  }

  // Apply `fn` with the first `N` elements of `t`, for compile-time `N`.
  template <std::size_t N, typename Tuple, typename Fn, std::size_t... I>
  static void ApplyPrefixImpl(Tuple &&t, Fn &&fn, std::index_sequence<I...>) {
    std::forward<Fn>(fn)(std::get<I>(std::forward<Tuple>(t))...);
  }

  template <std::size_t N, typename Tuple, typename Fn>
  static void ApplyPrefix(Tuple &&t, Fn &&fn) {
    ApplyPrefixImpl<N>(std::forward<Tuple>(t), std::forward<Fn>(fn),
                       std::make_index_sequence<N>{});
  }

  // Call `fn` with a runtime-selected prefix of `t`: exactly `call_arity`
  // leading elements. `Is...` enumerates every compile-time count in
  // `[0, sizeof...(Args)]`; the runtime check picks the matching one.
  template <typename Tuple, std::size_t... Is, typename Fn>
  static void CallWithArity(size_t call_arity, Tuple &&t,
                            std::index_sequence<Is...>, Fn &&fn) {
    (void)std::initializer_list<int>{(
        Is == call_arity
            ? (ApplyPrefix<Is>(std::forward<Tuple>(t), std::forward<Fn>(fn)), 0)
            : 0)...};
  }

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

  // ScopedPythonObject is non-copyable — passing it through the generic
  // TransformBack would trigger the deleted copy ctor. It manages its own
  // cleanup via the destructor when the transformed-args tuple destructs, so
  // there is nothing to reverse-transform back into the original arg.
  template <typename T, typename SB>
  void TransformBack(T &original_arg,
                     python::ScopedPythonObject<SB> &transformed_arg,
                     Status &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 <>
llvm::Expected<StructuredData::ArraySP>
ScriptedPythonInterface::ExtractValueFromPythonObject<StructuredData::ArraySP>(
    python::PythonObject &p);

template <>
llvm::Expected<StructuredData::DictionarySP>
ScriptedPythonInterface::ExtractValueFromPythonObject<
    StructuredData::DictionarySP>(python::PythonObject &p);

template <>
llvm::Expected<Status>
ScriptedPythonInterface::ExtractValueFromPythonObject<Status>(
    python::PythonObject &p);

template <>
llvm::Expected<Event *>
ScriptedPythonInterface::ExtractValueFromPythonObject<Event *>(
    python::PythonObject &p);

template <>
llvm::Expected<SymbolContext>
ScriptedPythonInterface::ExtractValueFromPythonObject<SymbolContext>(
    python::PythonObject &p);

template <>
llvm::Expected<lldb::StreamSP>
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StreamSP>(
    python::PythonObject &p);

template <>
llvm::Expected<lldb::ThreadSP>
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::ThreadSP>(
    python::PythonObject &p);

template <>
llvm::Expected<lldb::StackFrameSP>
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StackFrameSP>(
    python::PythonObject &p);

template <>
llvm::Expected<lldb::BreakpointSP>
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::BreakpointSP>(
    python::PythonObject &p);

template <>
llvm::Expected<lldb::BreakpointLocationSP>
ScriptedPythonInterface::ExtractValueFromPythonObject<
    lldb::BreakpointLocationSP>(python::PythonObject &p);

template <>
llvm::Expected<lldb::ProcessAttachInfoSP>
ScriptedPythonInterface::ExtractValueFromPythonObject<
    lldb::ProcessAttachInfoSP>(python::PythonObject &p);

template <>
llvm::Expected<lldb::ProcessLaunchInfoSP>
ScriptedPythonInterface::ExtractValueFromPythonObject<
    lldb::ProcessLaunchInfoSP>(python::PythonObject &p);

template <>
llvm::Expected<lldb::DataExtractorSP>
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>(
    python::PythonObject &p);

template <>
llvm::Expected<lldb::ThreadPlanSP>
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::ThreadPlanSP>(
    python::PythonObject &p);

template <>
llvm::Expected<std::optional<MemoryRegionInfo>>
ScriptedPythonInterface::ExtractValueFromPythonObject<
    std::optional<MemoryRegionInfo>>(python::PythonObject &p);

template <>
llvm::Expected<lldb::ExecutionContextRefSP>
ScriptedPythonInterface::ExtractValueFromPythonObject<
    lldb::ExecutionContextRefSP>(python::PythonObject &p);

template <>
llvm::Expected<lldb::DescriptionLevel>
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DescriptionLevel>(
    python::PythonObject &p);

template <>
llvm::Expected<lldb::StepType>
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StepType>(
    python::PythonObject &p);

template <>
llvm::Expected<lldb::StackFrameListSP>
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StackFrameListSP>(
    python::PythonObject &p);

template <>
llvm::Expected<lldb::ValueObjectSP>
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::ValueObjectSP>(
    python::PythonObject &p);

template <>
llvm::Expected<lldb::TargetSP>
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::TargetSP>(
    python::PythonObject &p);

template <>
llvm::Expected<lldb::ValueObjectListSP>
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::ValueObjectListSP>(
    python::PythonObject &p);

template <>
llvm::Expected<std::optional<lldb::ValueType>>
ScriptedPythonInterface::ExtractValueFromPythonObject<
    std::optional<lldb::ValueType>>(python::PythonObject &p);

template <>
llvm::Expected<lldb::DebuggerSP>
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DebuggerSP>(
    python::PythonObject &p);

template <>
llvm::Expected<std::vector<std::string>>
ScriptedPythonInterface::ExtractValueFromPythonObject<std::vector<std::string>>(
    python::PythonObject &p);

} // namespace lldb_private

#endif // LLDB_SOURCE_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H
