1b1c73532SDimitry Andric //===-- ScriptedPythonInterface.h -------------------------------*- C++ -*-===// 2b1c73532SDimitry Andric // 3b1c73532SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4b1c73532SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5b1c73532SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6b1c73532SDimitry Andric // 7b1c73532SDimitry Andric //===----------------------------------------------------------------------===// 8b1c73532SDimitry Andric 9b1c73532SDimitry Andric #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H 10b1c73532SDimitry Andric #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H 11b1c73532SDimitry Andric 12b1c73532SDimitry Andric #if LLDB_ENABLE_PYTHON 13b1c73532SDimitry Andric 14b1c73532SDimitry Andric #include <optional> 15b1c73532SDimitry Andric #include <sstream> 16b1c73532SDimitry Andric #include <tuple> 17b1c73532SDimitry Andric #include <type_traits> 18b1c73532SDimitry Andric #include <utility> 19b1c73532SDimitry Andric 20b1c73532SDimitry Andric #include "lldb/Host/Config.h" 21b1c73532SDimitry Andric #include "lldb/Interpreter/Interfaces/ScriptedInterface.h" 22b1c73532SDimitry Andric #include "lldb/Utility/DataBufferHeap.h" 23b1c73532SDimitry Andric 24b1c73532SDimitry Andric #include "../PythonDataObjects.h" 25b1c73532SDimitry Andric #include "../SWIGPythonBridge.h" 26b1c73532SDimitry Andric #include "../ScriptInterpreterPythonImpl.h" 27b1c73532SDimitry Andric 28b1c73532SDimitry Andric namespace lldb_private { 29b1c73532SDimitry Andric class ScriptInterpreterPythonImpl; 30b1c73532SDimitry Andric class ScriptedPythonInterface : virtual public ScriptedInterface { 31b1c73532SDimitry Andric public: 32b1c73532SDimitry Andric ScriptedPythonInterface(ScriptInterpreterPythonImpl &interpreter); 33b1c73532SDimitry Andric ~ScriptedPythonInterface() override = default; 34b1c73532SDimitry Andric 35b1c73532SDimitry Andric enum class AbstractMethodCheckerCases { 36b1c73532SDimitry Andric eNotImplemented, 37b1c73532SDimitry Andric eNotAllocated, 38b1c73532SDimitry Andric eNotCallable, 39b1c73532SDimitry Andric eValid 40b1c73532SDimitry Andric }; 41b1c73532SDimitry Andric 42b1c73532SDimitry Andric llvm::Expected<std::map<llvm::StringLiteral, AbstractMethodCheckerCases>> CheckAbstractMethodImplementation(const python::PythonDictionary & class_dict)43b1c73532SDimitry Andric CheckAbstractMethodImplementation( 44b1c73532SDimitry Andric const python::PythonDictionary &class_dict) const { 45b1c73532SDimitry Andric 46b1c73532SDimitry Andric using namespace python; 47b1c73532SDimitry Andric 48b1c73532SDimitry Andric std::map<llvm::StringLiteral, AbstractMethodCheckerCases> checker; 49b1c73532SDimitry Andric #define SET_ERROR_AND_CONTINUE(method_name, error) \ 50b1c73532SDimitry Andric { \ 51b1c73532SDimitry Andric checker[method_name] = error; \ 52b1c73532SDimitry Andric continue; \ 53b1c73532SDimitry Andric } 54b1c73532SDimitry Andric 55b1c73532SDimitry Andric for (const llvm::StringLiteral &method_name : GetAbstractMethods()) { 56b1c73532SDimitry Andric if (!class_dict.HasKey(method_name)) 57b1c73532SDimitry Andric SET_ERROR_AND_CONTINUE(method_name, 58b1c73532SDimitry Andric AbstractMethodCheckerCases::eNotImplemented) 59b1c73532SDimitry Andric auto callable_or_err = class_dict.GetItem(method_name); 60b1c73532SDimitry Andric if (!callable_or_err) 61b1c73532SDimitry Andric SET_ERROR_AND_CONTINUE(method_name, 62b1c73532SDimitry Andric AbstractMethodCheckerCases::eNotAllocated) 63b1c73532SDimitry Andric if (!PythonCallable::Check(callable_or_err.get().get())) 64b1c73532SDimitry Andric SET_ERROR_AND_CONTINUE(method_name, 65b1c73532SDimitry Andric AbstractMethodCheckerCases::eNotCallable) 66b1c73532SDimitry Andric checker[method_name] = AbstractMethodCheckerCases::eValid; 67b1c73532SDimitry Andric } 68b1c73532SDimitry Andric 69b1c73532SDimitry Andric #undef HANDLE_ERROR 70b1c73532SDimitry Andric 71b1c73532SDimitry Andric return checker; 72b1c73532SDimitry Andric } 73b1c73532SDimitry Andric 74b1c73532SDimitry Andric template <typename... Args> 75b1c73532SDimitry Andric llvm::Expected<StructuredData::GenericSP> CreatePluginObject(llvm::StringRef class_name,StructuredData::Generic * script_obj,Args...args)76b1c73532SDimitry Andric CreatePluginObject(llvm::StringRef class_name, 77b1c73532SDimitry Andric StructuredData::Generic *script_obj, Args... args) { 78b1c73532SDimitry Andric using namespace python; 79b1c73532SDimitry Andric using Locker = ScriptInterpreterPythonImpl::Locker; 80b1c73532SDimitry Andric 81b1c73532SDimitry Andric auto create_error = [](std::string message) { 82b1c73532SDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), message); 83b1c73532SDimitry Andric }; 84b1c73532SDimitry Andric 85b1c73532SDimitry Andric bool has_class_name = !class_name.empty(); 86b1c73532SDimitry Andric bool has_interpreter_dict = 87b1c73532SDimitry Andric !(llvm::StringRef(m_interpreter.GetDictionaryName()).empty()); 88b1c73532SDimitry Andric if (!has_class_name && !has_interpreter_dict && !script_obj) { 89b1c73532SDimitry Andric if (!has_class_name) 90b1c73532SDimitry Andric return create_error("Missing script class name."); 91b1c73532SDimitry Andric else if (!has_interpreter_dict) 92b1c73532SDimitry Andric return create_error("Invalid script interpreter dictionary."); 93b1c73532SDimitry Andric else 94b1c73532SDimitry Andric return create_error("Missing scripting object."); 95b1c73532SDimitry Andric } 96b1c73532SDimitry Andric 97b1c73532SDimitry Andric Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, 98b1c73532SDimitry Andric Locker::FreeLock); 99b1c73532SDimitry Andric 100b1c73532SDimitry Andric PythonObject result = {}; 101b1c73532SDimitry Andric 102b1c73532SDimitry Andric if (script_obj) { 103b1c73532SDimitry Andric result = PythonObject(PyRefType::Borrowed, 104b1c73532SDimitry Andric static_cast<PyObject *>(script_obj->GetValue())); 105b1c73532SDimitry Andric } else { 106b1c73532SDimitry Andric auto dict = 107b1c73532SDimitry Andric PythonModule::MainModule().ResolveName<python::PythonDictionary>( 108b1c73532SDimitry Andric m_interpreter.GetDictionaryName()); 109b1c73532SDimitry Andric if (!dict.IsAllocated()) 110b1c73532SDimitry Andric return create_error( 111b1c73532SDimitry Andric llvm::formatv("Could not find interpreter dictionary: %s", 112b1c73532SDimitry Andric m_interpreter.GetDictionaryName())); 113b1c73532SDimitry Andric 114b1c73532SDimitry Andric auto init = 115b1c73532SDimitry Andric PythonObject::ResolveNameWithDictionary<python::PythonCallable>( 116b1c73532SDimitry Andric class_name, dict); 117b1c73532SDimitry Andric if (!init.IsAllocated()) 118ac9a064cSDimitry Andric return create_error(llvm::formatv("Could not find script class: {0}", 119b1c73532SDimitry Andric class_name.data())); 120b1c73532SDimitry Andric 121b1c73532SDimitry Andric std::tuple<Args...> original_args = std::forward_as_tuple(args...); 122b1c73532SDimitry Andric auto transformed_args = TransformArgs(original_args); 123b1c73532SDimitry Andric 124b1c73532SDimitry Andric std::string error_string; 125b1c73532SDimitry Andric llvm::Expected<PythonCallable::ArgInfo> arg_info = init.GetArgInfo(); 126b1c73532SDimitry Andric if (!arg_info) { 127b1c73532SDimitry Andric llvm::handleAllErrors( 128b1c73532SDimitry Andric arg_info.takeError(), 129b1c73532SDimitry Andric [&](PythonException &E) { error_string.append(E.ReadBacktrace()); }, 130b1c73532SDimitry Andric [&](const llvm::ErrorInfoBase &E) { 131b1c73532SDimitry Andric error_string.append(E.message()); 132b1c73532SDimitry Andric }); 133b1c73532SDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 134b1c73532SDimitry Andric error_string); 135b1c73532SDimitry Andric } 136b1c73532SDimitry Andric 137b1c73532SDimitry Andric llvm::Expected<PythonObject> expected_return_object = 138b1c73532SDimitry Andric create_error("Resulting object is not initialized."); 139b1c73532SDimitry Andric 140b1c73532SDimitry Andric std::apply( 141b1c73532SDimitry Andric [&init, &expected_return_object](auto &&...args) { 142b1c73532SDimitry Andric llvm::consumeError(expected_return_object.takeError()); 143b1c73532SDimitry Andric expected_return_object = init(args...); 144b1c73532SDimitry Andric }, 145b1c73532SDimitry Andric transformed_args); 146b1c73532SDimitry Andric 147b1c73532SDimitry Andric if (!expected_return_object) 148b1c73532SDimitry Andric return expected_return_object.takeError(); 149b1c73532SDimitry Andric result = expected_return_object.get(); 150b1c73532SDimitry Andric } 151b1c73532SDimitry Andric 152b1c73532SDimitry Andric if (!result.IsValid()) 153b1c73532SDimitry Andric return create_error("Resulting object is not a valid Python Object."); 154b1c73532SDimitry Andric if (!result.HasAttribute("__class__")) 155b1c73532SDimitry Andric return create_error("Resulting object doesn't have '__class__' member."); 156b1c73532SDimitry Andric 157b1c73532SDimitry Andric PythonObject obj_class = result.GetAttributeValue("__class__"); 158b1c73532SDimitry Andric if (!obj_class.IsValid()) 159b1c73532SDimitry Andric return create_error("Resulting class object is not a valid."); 160b1c73532SDimitry Andric if (!obj_class.HasAttribute("__name__")) 161b1c73532SDimitry Andric return create_error( 162b1c73532SDimitry Andric "Resulting object class doesn't have '__name__' member."); 163b1c73532SDimitry Andric PythonString obj_class_name = 164b1c73532SDimitry Andric obj_class.GetAttributeValue("__name__").AsType<PythonString>(); 165b1c73532SDimitry Andric 166b1c73532SDimitry Andric PythonObject object_class_mapping_proxy = 167b1c73532SDimitry Andric obj_class.GetAttributeValue("__dict__"); 168b1c73532SDimitry Andric if (!obj_class.HasAttribute("__dict__")) 169b1c73532SDimitry Andric return create_error( 170b1c73532SDimitry Andric "Resulting object class doesn't have '__dict__' member."); 171b1c73532SDimitry Andric 172b1c73532SDimitry Andric PythonCallable dict_converter = PythonModule::BuiltinsModule() 173b1c73532SDimitry Andric .ResolveName("dict") 174b1c73532SDimitry Andric .AsType<PythonCallable>(); 175b1c73532SDimitry Andric if (!dict_converter.IsAllocated()) 176b1c73532SDimitry Andric return create_error( 177b1c73532SDimitry Andric "Python 'builtins' module doesn't have 'dict' class."); 178b1c73532SDimitry Andric 179b1c73532SDimitry Andric PythonDictionary object_class_dict = 180b1c73532SDimitry Andric dict_converter(object_class_mapping_proxy).AsType<PythonDictionary>(); 181b1c73532SDimitry Andric if (!object_class_dict.IsAllocated()) 182b1c73532SDimitry Andric return create_error("Coudn't create dictionary from resulting object " 183b1c73532SDimitry Andric "class mapping proxy object."); 184b1c73532SDimitry Andric 185b1c73532SDimitry Andric auto checker_or_err = CheckAbstractMethodImplementation(object_class_dict); 186b1c73532SDimitry Andric if (!checker_or_err) 187b1c73532SDimitry Andric return checker_or_err.takeError(); 188b1c73532SDimitry Andric 189b1c73532SDimitry Andric for (const auto &method_checker : *checker_or_err) 190b1c73532SDimitry Andric switch (method_checker.second) { 191b1c73532SDimitry Andric case AbstractMethodCheckerCases::eNotImplemented: 192b1c73532SDimitry Andric LLDB_LOG(GetLog(LLDBLog::Script), 193b1c73532SDimitry Andric "Abstract method {0}.{1} not implemented.", 194b1c73532SDimitry Andric obj_class_name.GetString(), method_checker.first); 195b1c73532SDimitry Andric break; 196b1c73532SDimitry Andric case AbstractMethodCheckerCases::eNotAllocated: 197b1c73532SDimitry Andric LLDB_LOG(GetLog(LLDBLog::Script), 198b1c73532SDimitry Andric "Abstract method {0}.{1} not allocated.", 199b1c73532SDimitry Andric obj_class_name.GetString(), method_checker.first); 200b1c73532SDimitry Andric break; 201b1c73532SDimitry Andric case AbstractMethodCheckerCases::eNotCallable: 202b1c73532SDimitry Andric LLDB_LOG(GetLog(LLDBLog::Script), 203b1c73532SDimitry Andric "Abstract method {0}.{1} not callable.", 204b1c73532SDimitry Andric obj_class_name.GetString(), method_checker.first); 205b1c73532SDimitry Andric break; 206b1c73532SDimitry Andric case AbstractMethodCheckerCases::eValid: 207b1c73532SDimitry Andric LLDB_LOG(GetLog(LLDBLog::Script), 208b1c73532SDimitry Andric "Abstract method {0}.{1} implemented & valid.", 209b1c73532SDimitry Andric obj_class_name.GetString(), method_checker.first); 210b1c73532SDimitry Andric break; 211b1c73532SDimitry Andric } 212b1c73532SDimitry Andric 213b1c73532SDimitry Andric for (const auto &method_checker : *checker_or_err) 214b1c73532SDimitry Andric if (method_checker.second != AbstractMethodCheckerCases::eValid) 215b1c73532SDimitry Andric return create_error( 216b1c73532SDimitry Andric llvm::formatv("Abstract method {0}.{1} missing. Enable lldb " 217b1c73532SDimitry Andric "script log for more details.", 218b1c73532SDimitry Andric obj_class_name.GetString(), method_checker.first)); 219b1c73532SDimitry Andric 220b1c73532SDimitry Andric m_object_instance_sp = StructuredData::GenericSP( 221b1c73532SDimitry Andric new StructuredPythonObject(std::move(result))); 222b1c73532SDimitry Andric return m_object_instance_sp; 223b1c73532SDimitry Andric } 224b1c73532SDimitry Andric 225b1c73532SDimitry Andric protected: 226b1c73532SDimitry Andric template <typename T = StructuredData::ObjectSP> ExtractValueFromPythonObject(python::PythonObject & p,Status & error)227b1c73532SDimitry Andric T ExtractValueFromPythonObject(python::PythonObject &p, Status &error) { 228b1c73532SDimitry Andric return p.CreateStructuredObject(); 229b1c73532SDimitry Andric } 230b1c73532SDimitry Andric 231b1c73532SDimitry Andric template <typename T = StructuredData::ObjectSP, typename... Args> Dispatch(llvm::StringRef method_name,Status & error,Args &&...args)232b1c73532SDimitry Andric T Dispatch(llvm::StringRef method_name, Status &error, Args &&...args) { 233b1c73532SDimitry Andric using namespace python; 234b1c73532SDimitry Andric using Locker = ScriptInterpreterPythonImpl::Locker; 235b1c73532SDimitry Andric 236b1c73532SDimitry Andric std::string caller_signature = 237b1c73532SDimitry Andric llvm::Twine(LLVM_PRETTY_FUNCTION + llvm::Twine(" (") + 238b1c73532SDimitry Andric llvm::Twine(method_name) + llvm::Twine(")")) 239b1c73532SDimitry Andric .str(); 240b1c73532SDimitry Andric if (!m_object_instance_sp) 241b1c73532SDimitry Andric return ErrorWithMessage<T>(caller_signature, "Python object ill-formed", 242b1c73532SDimitry Andric error); 243b1c73532SDimitry Andric 244b1c73532SDimitry Andric Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, 245b1c73532SDimitry Andric Locker::FreeLock); 246b1c73532SDimitry Andric 247b1c73532SDimitry Andric PythonObject implementor(PyRefType::Borrowed, 248b1c73532SDimitry Andric (PyObject *)m_object_instance_sp->GetValue()); 249b1c73532SDimitry Andric 250b1c73532SDimitry Andric if (!implementor.IsAllocated()) 251ac9a064cSDimitry Andric return llvm::is_contained(GetAbstractMethods(), method_name) 252ac9a064cSDimitry Andric ? ErrorWithMessage<T>(caller_signature, 253ac9a064cSDimitry Andric "Python implementor not allocated.", 254ac9a064cSDimitry Andric error) 255ac9a064cSDimitry Andric : T{}; 256b1c73532SDimitry Andric 257b1c73532SDimitry Andric std::tuple<Args...> original_args = std::forward_as_tuple(args...); 258b1c73532SDimitry Andric auto transformed_args = TransformArgs(original_args); 259b1c73532SDimitry Andric 260b1c73532SDimitry Andric llvm::Expected<PythonObject> expected_return_object = 261b1c73532SDimitry Andric llvm::make_error<llvm::StringError>("Not initialized.", 262b1c73532SDimitry Andric llvm::inconvertibleErrorCode()); 263b1c73532SDimitry Andric std::apply( 264b1c73532SDimitry Andric [&implementor, &method_name, &expected_return_object](auto &&...args) { 265b1c73532SDimitry Andric llvm::consumeError(expected_return_object.takeError()); 266b1c73532SDimitry Andric expected_return_object = 267b1c73532SDimitry Andric implementor.CallMethod(method_name.data(), args...); 268b1c73532SDimitry Andric }, 269b1c73532SDimitry Andric transformed_args); 270b1c73532SDimitry Andric 271b1c73532SDimitry Andric if (llvm::Error e = expected_return_object.takeError()) { 272b1c73532SDimitry Andric error.SetErrorString(llvm::toString(std::move(e)).c_str()); 273b1c73532SDimitry Andric return ErrorWithMessage<T>(caller_signature, 274b1c73532SDimitry Andric "Python method could not be called.", error); 275b1c73532SDimitry Andric } 276b1c73532SDimitry Andric 277b1c73532SDimitry Andric PythonObject py_return = std::move(expected_return_object.get()); 278b1c73532SDimitry Andric 279b1c73532SDimitry Andric // Now that we called the python method with the transformed arguments, 280b1c73532SDimitry Andric // we need to interate again over both the original and transformed 281b1c73532SDimitry Andric // parameter pack, and transform back the parameter that were passed in 282b1c73532SDimitry Andric // the original parameter pack as references or pointers. 283b1c73532SDimitry Andric if (sizeof...(Args) > 0) 284b1c73532SDimitry Andric if (!ReassignPtrsOrRefsArgs(original_args, transformed_args)) 285b1c73532SDimitry Andric return ErrorWithMessage<T>( 286b1c73532SDimitry Andric caller_signature, 287b1c73532SDimitry Andric "Couldn't re-assign reference and pointer arguments.", error); 288b1c73532SDimitry Andric 289b1c73532SDimitry Andric if (!py_return.IsAllocated()) 290b1c73532SDimitry Andric return {}; 291b1c73532SDimitry Andric return ExtractValueFromPythonObject<T>(py_return, error); 292b1c73532SDimitry Andric } 293b1c73532SDimitry Andric 294b1c73532SDimitry Andric template <typename... Args> GetStatusFromMethod(llvm::StringRef method_name,Args &&...args)295b1c73532SDimitry Andric Status GetStatusFromMethod(llvm::StringRef method_name, Args &&...args) { 296b1c73532SDimitry Andric Status error; 297b1c73532SDimitry Andric Dispatch<Status>(method_name, error, std::forward<Args>(args)...); 298b1c73532SDimitry Andric 299b1c73532SDimitry Andric return error; 300b1c73532SDimitry Andric } 301b1c73532SDimitry Andric Transform(T object)302b1c73532SDimitry Andric template <typename T> T Transform(T object) { 303b1c73532SDimitry Andric // No Transformation for generic usage 304b1c73532SDimitry Andric return {object}; 305b1c73532SDimitry Andric } 306b1c73532SDimitry Andric Transform(bool arg)307b1c73532SDimitry Andric python::PythonObject Transform(bool arg) { 308b1c73532SDimitry Andric // Boolean arguments need to be turned into python objects. 309b1c73532SDimitry Andric return python::PythonBoolean(arg); 310b1c73532SDimitry Andric } 311b1c73532SDimitry Andric Transform(Status arg)312b1c73532SDimitry Andric python::PythonObject Transform(Status arg) { 313b1c73532SDimitry Andric return python::SWIGBridge::ToSWIGWrapper(arg); 314b1c73532SDimitry Andric } 315b1c73532SDimitry Andric Transform(const StructuredDataImpl & arg)316b1c73532SDimitry Andric python::PythonObject Transform(const StructuredDataImpl &arg) { 317b1c73532SDimitry Andric return python::SWIGBridge::ToSWIGWrapper(arg); 318b1c73532SDimitry Andric } 319b1c73532SDimitry Andric Transform(lldb::ExecutionContextRefSP arg)320b1c73532SDimitry Andric python::PythonObject Transform(lldb::ExecutionContextRefSP arg) { 321b1c73532SDimitry Andric return python::SWIGBridge::ToSWIGWrapper(arg); 322b1c73532SDimitry Andric } 323b1c73532SDimitry Andric Transform(lldb::ProcessSP arg)324b1c73532SDimitry Andric python::PythonObject Transform(lldb::ProcessSP arg) { 325b1c73532SDimitry Andric return python::SWIGBridge::ToSWIGWrapper(arg); 326b1c73532SDimitry Andric } 327b1c73532SDimitry Andric Transform(lldb::ThreadPlanSP arg)328ac9a064cSDimitry Andric python::PythonObject Transform(lldb::ThreadPlanSP arg) { 329ac9a064cSDimitry Andric return python::SWIGBridge::ToSWIGWrapper(arg); 330ac9a064cSDimitry Andric } 331ac9a064cSDimitry Andric Transform(lldb::ProcessAttachInfoSP arg)332b1c73532SDimitry Andric python::PythonObject Transform(lldb::ProcessAttachInfoSP arg) { 333b1c73532SDimitry Andric return python::SWIGBridge::ToSWIGWrapper(arg); 334b1c73532SDimitry Andric } 335b1c73532SDimitry Andric Transform(lldb::ProcessLaunchInfoSP arg)336b1c73532SDimitry Andric python::PythonObject Transform(lldb::ProcessLaunchInfoSP arg) { 337b1c73532SDimitry Andric return python::SWIGBridge::ToSWIGWrapper(arg); 338b1c73532SDimitry Andric } 339b1c73532SDimitry Andric Transform(Event * arg)340ac9a064cSDimitry Andric python::PythonObject Transform(Event *arg) { 341ac9a064cSDimitry Andric return python::SWIGBridge::ToSWIGWrapper(arg); 342ac9a064cSDimitry Andric } 343ac9a064cSDimitry Andric Transform(lldb::StreamSP arg)344ac9a064cSDimitry Andric python::PythonObject Transform(lldb::StreamSP arg) { 345ac9a064cSDimitry Andric return python::SWIGBridge::ToSWIGWrapper(arg.get()); 346ac9a064cSDimitry Andric } 347ac9a064cSDimitry Andric Transform(lldb::DataExtractorSP arg)348b1c73532SDimitry Andric python::PythonObject Transform(lldb::DataExtractorSP arg) { 349b1c73532SDimitry Andric return python::SWIGBridge::ToSWIGWrapper(arg); 350b1c73532SDimitry Andric } 351b1c73532SDimitry Andric 352b1c73532SDimitry Andric template <typename T, typename U> ReverseTransform(T & original_arg,U transformed_arg,Status & error)353b1c73532SDimitry Andric void ReverseTransform(T &original_arg, U transformed_arg, Status &error) { 354b1c73532SDimitry Andric // If U is not a PythonObject, don't touch it! 355b1c73532SDimitry Andric return; 356b1c73532SDimitry Andric } 357b1c73532SDimitry Andric 358b1c73532SDimitry Andric template <typename T> ReverseTransform(T & original_arg,python::PythonObject transformed_arg,Status & error)359b1c73532SDimitry Andric void ReverseTransform(T &original_arg, python::PythonObject transformed_arg, 360b1c73532SDimitry Andric Status &error) { 361b1c73532SDimitry Andric original_arg = ExtractValueFromPythonObject<T>(transformed_arg, error); 362b1c73532SDimitry Andric } 363b1c73532SDimitry Andric ReverseTransform(bool & original_arg,python::PythonObject transformed_arg,Status & error)364b1c73532SDimitry Andric void ReverseTransform(bool &original_arg, 365b1c73532SDimitry Andric python::PythonObject transformed_arg, Status &error) { 366b1c73532SDimitry Andric python::PythonBoolean boolean_arg = python::PythonBoolean( 367b1c73532SDimitry Andric python::PyRefType::Borrowed, transformed_arg.get()); 368b1c73532SDimitry Andric if (boolean_arg.IsValid()) 369b1c73532SDimitry Andric original_arg = boolean_arg.GetValue(); 370b1c73532SDimitry Andric else 371b1c73532SDimitry Andric error.SetErrorString( 372b1c73532SDimitry Andric llvm::formatv("{}: Invalid boolean argument.", LLVM_PRETTY_FUNCTION) 373b1c73532SDimitry Andric .str()); 374b1c73532SDimitry Andric } 375b1c73532SDimitry Andric 376b1c73532SDimitry Andric template <std::size_t... I, typename... Args> TransformTuple(const std::tuple<Args...> & args,std::index_sequence<I...>)377b1c73532SDimitry Andric auto TransformTuple(const std::tuple<Args...> &args, 378b1c73532SDimitry Andric std::index_sequence<I...>) { 379b1c73532SDimitry Andric return std::make_tuple(Transform(std::get<I>(args))...); 380b1c73532SDimitry Andric } 381b1c73532SDimitry Andric 382b1c73532SDimitry Andric // This will iterate over the Dispatch parameter pack and replace in-place 383b1c73532SDimitry Andric // every `lldb_private` argument that has a SB counterpart. 384b1c73532SDimitry Andric template <typename... Args> TransformArgs(const std::tuple<Args...> & args)385b1c73532SDimitry Andric auto TransformArgs(const std::tuple<Args...> &args) { 386b1c73532SDimitry Andric return TransformTuple(args, std::make_index_sequence<sizeof...(Args)>()); 387b1c73532SDimitry Andric } 388b1c73532SDimitry Andric 389b1c73532SDimitry Andric template <typename T, typename U> TransformBack(T & original_arg,U transformed_arg,Status & error)390b1c73532SDimitry Andric void TransformBack(T &original_arg, U transformed_arg, Status &error) { 391b1c73532SDimitry Andric ReverseTransform(original_arg, transformed_arg, error); 392b1c73532SDimitry Andric } 393b1c73532SDimitry Andric 394b1c73532SDimitry Andric template <std::size_t... I, typename... Ts, typename... Us> ReassignPtrsOrRefsArgs(std::tuple<Ts...> & original_args,std::tuple<Us...> & transformed_args,std::index_sequence<I...>)395b1c73532SDimitry Andric bool ReassignPtrsOrRefsArgs(std::tuple<Ts...> &original_args, 396b1c73532SDimitry Andric std::tuple<Us...> &transformed_args, 397b1c73532SDimitry Andric std::index_sequence<I...>) { 398b1c73532SDimitry Andric Status error; 399b1c73532SDimitry Andric (TransformBack(std::get<I>(original_args), std::get<I>(transformed_args), 400b1c73532SDimitry Andric error), 401b1c73532SDimitry Andric ...); 402b1c73532SDimitry Andric return error.Success(); 403b1c73532SDimitry Andric } 404b1c73532SDimitry Andric 405b1c73532SDimitry Andric template <typename... Ts, typename... Us> ReassignPtrsOrRefsArgs(std::tuple<Ts...> & original_args,std::tuple<Us...> & transformed_args)406b1c73532SDimitry Andric bool ReassignPtrsOrRefsArgs(std::tuple<Ts...> &original_args, 407b1c73532SDimitry Andric std::tuple<Us...> &transformed_args) { 408b1c73532SDimitry Andric if (sizeof...(Ts) != sizeof...(Us)) 409b1c73532SDimitry Andric return false; 410b1c73532SDimitry Andric 411b1c73532SDimitry Andric return ReassignPtrsOrRefsArgs(original_args, transformed_args, 412b1c73532SDimitry Andric std::make_index_sequence<sizeof...(Ts)>()); 413b1c73532SDimitry Andric } 414b1c73532SDimitry Andric 415b1c73532SDimitry Andric template <typename T, typename... Args> FormatArgs(std::string & fmt,T arg,Args...args)416b1c73532SDimitry Andric void FormatArgs(std::string &fmt, T arg, Args... args) const { 417b1c73532SDimitry Andric FormatArgs(fmt, arg); 418b1c73532SDimitry Andric FormatArgs(fmt, args...); 419b1c73532SDimitry Andric } 420b1c73532SDimitry Andric FormatArgs(std::string & fmt,T arg)421b1c73532SDimitry Andric template <typename T> void FormatArgs(std::string &fmt, T arg) const { 422b1c73532SDimitry Andric fmt += python::PythonFormat<T>::format; 423b1c73532SDimitry Andric } 424b1c73532SDimitry Andric FormatArgs(std::string & fmt)425b1c73532SDimitry Andric void FormatArgs(std::string &fmt) const {} 426b1c73532SDimitry Andric 427b1c73532SDimitry Andric // The lifetime is managed by the ScriptInterpreter 428b1c73532SDimitry Andric ScriptInterpreterPythonImpl &m_interpreter; 429b1c73532SDimitry Andric }; 430b1c73532SDimitry Andric 431b1c73532SDimitry Andric template <> 432b1c73532SDimitry Andric StructuredData::ArraySP 433b1c73532SDimitry Andric ScriptedPythonInterface::ExtractValueFromPythonObject<StructuredData::ArraySP>( 434b1c73532SDimitry Andric python::PythonObject &p, Status &error); 435b1c73532SDimitry Andric 436b1c73532SDimitry Andric template <> 437b1c73532SDimitry Andric StructuredData::DictionarySP 438b1c73532SDimitry Andric ScriptedPythonInterface::ExtractValueFromPythonObject< 439b1c73532SDimitry Andric StructuredData::DictionarySP>(python::PythonObject &p, Status &error); 440b1c73532SDimitry Andric 441b1c73532SDimitry Andric template <> 442b1c73532SDimitry Andric Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>( 443b1c73532SDimitry Andric python::PythonObject &p, Status &error); 444b1c73532SDimitry Andric 445b1c73532SDimitry Andric template <> 446ac9a064cSDimitry Andric Event *ScriptedPythonInterface::ExtractValueFromPythonObject<Event *>( 447ac9a064cSDimitry Andric python::PythonObject &p, Status &error); 448ac9a064cSDimitry Andric 449ac9a064cSDimitry Andric template <> 450ac9a064cSDimitry Andric lldb::StreamSP 451ac9a064cSDimitry Andric ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StreamSP>( 452ac9a064cSDimitry Andric python::PythonObject &p, Status &error); 453ac9a064cSDimitry Andric 454ac9a064cSDimitry Andric template <> 455b1c73532SDimitry Andric lldb::BreakpointSP 456b1c73532SDimitry Andric ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::BreakpointSP>( 457b1c73532SDimitry Andric python::PythonObject &p, Status &error); 458b1c73532SDimitry Andric 459b1c73532SDimitry Andric template <> 460b1c73532SDimitry Andric lldb::ProcessAttachInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< 461b1c73532SDimitry Andric lldb::ProcessAttachInfoSP>(python::PythonObject &p, Status &error); 462b1c73532SDimitry Andric 463b1c73532SDimitry Andric template <> 464b1c73532SDimitry Andric lldb::ProcessLaunchInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< 465b1c73532SDimitry Andric lldb::ProcessLaunchInfoSP>(python::PythonObject &p, Status &error); 466b1c73532SDimitry Andric 467b1c73532SDimitry Andric template <> 468b1c73532SDimitry Andric lldb::DataExtractorSP 469b1c73532SDimitry Andric ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>( 470b1c73532SDimitry Andric python::PythonObject &p, Status &error); 471b1c73532SDimitry Andric 472b1c73532SDimitry Andric template <> 473b1c73532SDimitry Andric std::optional<MemoryRegionInfo> 474b1c73532SDimitry Andric ScriptedPythonInterface::ExtractValueFromPythonObject< 475b1c73532SDimitry Andric std::optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error); 476b1c73532SDimitry Andric 477b1c73532SDimitry Andric } // namespace lldb_private 478b1c73532SDimitry Andric 479b1c73532SDimitry Andric #endif // LLDB_ENABLE_PYTHON 480b1c73532SDimitry Andric #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H 481