15f757f3fSDimitry Andric //===-- ScriptedPythonInterface.h -------------------------------*- C++ -*-===// 25f757f3fSDimitry Andric // 35f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65f757f3fSDimitry Andric // 75f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 85f757f3fSDimitry Andric 95f757f3fSDimitry Andric #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H 105f757f3fSDimitry Andric #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H 115f757f3fSDimitry Andric 125f757f3fSDimitry Andric #if LLDB_ENABLE_PYTHON 135f757f3fSDimitry Andric 145f757f3fSDimitry Andric #include <optional> 155f757f3fSDimitry Andric #include <sstream> 165f757f3fSDimitry Andric #include <tuple> 175f757f3fSDimitry Andric #include <type_traits> 185f757f3fSDimitry Andric #include <utility> 195f757f3fSDimitry Andric 205f757f3fSDimitry Andric #include "lldb/Host/Config.h" 215f757f3fSDimitry Andric #include "lldb/Interpreter/Interfaces/ScriptedInterface.h" 225f757f3fSDimitry Andric #include "lldb/Utility/DataBufferHeap.h" 235f757f3fSDimitry Andric 245f757f3fSDimitry Andric #include "../PythonDataObjects.h" 255f757f3fSDimitry Andric #include "../SWIGPythonBridge.h" 265f757f3fSDimitry Andric #include "../ScriptInterpreterPythonImpl.h" 275f757f3fSDimitry Andric 285f757f3fSDimitry Andric namespace lldb_private { 295f757f3fSDimitry Andric class ScriptInterpreterPythonImpl; 305f757f3fSDimitry Andric class ScriptedPythonInterface : virtual public ScriptedInterface { 315f757f3fSDimitry Andric public: 325f757f3fSDimitry Andric ScriptedPythonInterface(ScriptInterpreterPythonImpl &interpreter); 335f757f3fSDimitry Andric ~ScriptedPythonInterface() override = default; 345f757f3fSDimitry Andric 355f757f3fSDimitry Andric enum class AbstractMethodCheckerCases { 365f757f3fSDimitry Andric eNotImplemented, 375f757f3fSDimitry Andric eNotAllocated, 385f757f3fSDimitry Andric eNotCallable, 395f757f3fSDimitry Andric eValid 405f757f3fSDimitry Andric }; 415f757f3fSDimitry Andric 425f757f3fSDimitry Andric llvm::Expected<std::map<llvm::StringLiteral, AbstractMethodCheckerCases>> 435f757f3fSDimitry Andric CheckAbstractMethodImplementation( 445f757f3fSDimitry Andric const python::PythonDictionary &class_dict) const { 455f757f3fSDimitry Andric 465f757f3fSDimitry Andric using namespace python; 475f757f3fSDimitry Andric 485f757f3fSDimitry Andric std::map<llvm::StringLiteral, AbstractMethodCheckerCases> checker; 495f757f3fSDimitry Andric #define SET_ERROR_AND_CONTINUE(method_name, error) \ 505f757f3fSDimitry Andric { \ 515f757f3fSDimitry Andric checker[method_name] = error; \ 525f757f3fSDimitry Andric continue; \ 535f757f3fSDimitry Andric } 545f757f3fSDimitry Andric 555f757f3fSDimitry Andric for (const llvm::StringLiteral &method_name : GetAbstractMethods()) { 565f757f3fSDimitry Andric if (!class_dict.HasKey(method_name)) 575f757f3fSDimitry Andric SET_ERROR_AND_CONTINUE(method_name, 585f757f3fSDimitry Andric AbstractMethodCheckerCases::eNotImplemented) 595f757f3fSDimitry Andric auto callable_or_err = class_dict.GetItem(method_name); 605f757f3fSDimitry Andric if (!callable_or_err) 615f757f3fSDimitry Andric SET_ERROR_AND_CONTINUE(method_name, 625f757f3fSDimitry Andric AbstractMethodCheckerCases::eNotAllocated) 635f757f3fSDimitry Andric if (!PythonCallable::Check(callable_or_err.get().get())) 645f757f3fSDimitry Andric SET_ERROR_AND_CONTINUE(method_name, 655f757f3fSDimitry Andric AbstractMethodCheckerCases::eNotCallable) 665f757f3fSDimitry Andric checker[method_name] = AbstractMethodCheckerCases::eValid; 675f757f3fSDimitry Andric } 685f757f3fSDimitry Andric 695f757f3fSDimitry Andric #undef HANDLE_ERROR 705f757f3fSDimitry Andric 715f757f3fSDimitry Andric return checker; 725f757f3fSDimitry Andric } 735f757f3fSDimitry Andric 745f757f3fSDimitry Andric template <typename... Args> 755f757f3fSDimitry Andric llvm::Expected<StructuredData::GenericSP> 765f757f3fSDimitry Andric CreatePluginObject(llvm::StringRef class_name, 775f757f3fSDimitry Andric StructuredData::Generic *script_obj, Args... args) { 785f757f3fSDimitry Andric using namespace python; 795f757f3fSDimitry Andric using Locker = ScriptInterpreterPythonImpl::Locker; 805f757f3fSDimitry Andric 815f757f3fSDimitry Andric auto create_error = [](std::string message) { 825f757f3fSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), message); 835f757f3fSDimitry Andric }; 845f757f3fSDimitry Andric 855f757f3fSDimitry Andric bool has_class_name = !class_name.empty(); 865f757f3fSDimitry Andric bool has_interpreter_dict = 875f757f3fSDimitry Andric !(llvm::StringRef(m_interpreter.GetDictionaryName()).empty()); 885f757f3fSDimitry Andric if (!has_class_name && !has_interpreter_dict && !script_obj) { 895f757f3fSDimitry Andric if (!has_class_name) 905f757f3fSDimitry Andric return create_error("Missing script class name."); 915f757f3fSDimitry Andric else if (!has_interpreter_dict) 925f757f3fSDimitry Andric return create_error("Invalid script interpreter dictionary."); 935f757f3fSDimitry Andric else 945f757f3fSDimitry Andric return create_error("Missing scripting object."); 955f757f3fSDimitry Andric } 965f757f3fSDimitry Andric 975f757f3fSDimitry Andric Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, 985f757f3fSDimitry Andric Locker::FreeLock); 995f757f3fSDimitry Andric 1005f757f3fSDimitry Andric PythonObject result = {}; 1015f757f3fSDimitry Andric 1025f757f3fSDimitry Andric if (script_obj) { 1035f757f3fSDimitry Andric result = PythonObject(PyRefType::Borrowed, 1045f757f3fSDimitry Andric static_cast<PyObject *>(script_obj->GetValue())); 1055f757f3fSDimitry Andric } else { 1065f757f3fSDimitry Andric auto dict = 1075f757f3fSDimitry Andric PythonModule::MainModule().ResolveName<python::PythonDictionary>( 1085f757f3fSDimitry Andric m_interpreter.GetDictionaryName()); 1095f757f3fSDimitry Andric if (!dict.IsAllocated()) 1105f757f3fSDimitry Andric return create_error( 1115f757f3fSDimitry Andric llvm::formatv("Could not find interpreter dictionary: %s", 1125f757f3fSDimitry Andric m_interpreter.GetDictionaryName())); 1135f757f3fSDimitry Andric 1145f757f3fSDimitry Andric auto init = 1155f757f3fSDimitry Andric PythonObject::ResolveNameWithDictionary<python::PythonCallable>( 1165f757f3fSDimitry Andric class_name, dict); 1175f757f3fSDimitry Andric if (!init.IsAllocated()) 118*0fca6ea1SDimitry Andric return create_error(llvm::formatv("Could not find script class: {0}", 1195f757f3fSDimitry Andric class_name.data())); 1205f757f3fSDimitry Andric 1215f757f3fSDimitry Andric std::tuple<Args...> original_args = std::forward_as_tuple(args...); 1225f757f3fSDimitry Andric auto transformed_args = TransformArgs(original_args); 1235f757f3fSDimitry Andric 1245f757f3fSDimitry Andric std::string error_string; 1255f757f3fSDimitry Andric llvm::Expected<PythonCallable::ArgInfo> arg_info = init.GetArgInfo(); 1265f757f3fSDimitry Andric if (!arg_info) { 1275f757f3fSDimitry Andric llvm::handleAllErrors( 1285f757f3fSDimitry Andric arg_info.takeError(), 1295f757f3fSDimitry Andric [&](PythonException &E) { error_string.append(E.ReadBacktrace()); }, 1305f757f3fSDimitry Andric [&](const llvm::ErrorInfoBase &E) { 1315f757f3fSDimitry Andric error_string.append(E.message()); 1325f757f3fSDimitry Andric }); 1335f757f3fSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 1345f757f3fSDimitry Andric error_string); 1355f757f3fSDimitry Andric } 1365f757f3fSDimitry Andric 1375f757f3fSDimitry Andric llvm::Expected<PythonObject> expected_return_object = 1385f757f3fSDimitry Andric create_error("Resulting object is not initialized."); 1395f757f3fSDimitry Andric 1405f757f3fSDimitry Andric std::apply( 1415f757f3fSDimitry Andric [&init, &expected_return_object](auto &&...args) { 1425f757f3fSDimitry Andric llvm::consumeError(expected_return_object.takeError()); 1435f757f3fSDimitry Andric expected_return_object = init(args...); 1445f757f3fSDimitry Andric }, 1455f757f3fSDimitry Andric transformed_args); 1465f757f3fSDimitry Andric 1475f757f3fSDimitry Andric if (!expected_return_object) 1485f757f3fSDimitry Andric return expected_return_object.takeError(); 1495f757f3fSDimitry Andric result = expected_return_object.get(); 1505f757f3fSDimitry Andric } 1515f757f3fSDimitry Andric 1525f757f3fSDimitry Andric if (!result.IsValid()) 1535f757f3fSDimitry Andric return create_error("Resulting object is not a valid Python Object."); 1545f757f3fSDimitry Andric if (!result.HasAttribute("__class__")) 1555f757f3fSDimitry Andric return create_error("Resulting object doesn't have '__class__' member."); 1565f757f3fSDimitry Andric 1575f757f3fSDimitry Andric PythonObject obj_class = result.GetAttributeValue("__class__"); 1585f757f3fSDimitry Andric if (!obj_class.IsValid()) 1595f757f3fSDimitry Andric return create_error("Resulting class object is not a valid."); 1605f757f3fSDimitry Andric if (!obj_class.HasAttribute("__name__")) 1615f757f3fSDimitry Andric return create_error( 1625f757f3fSDimitry Andric "Resulting object class doesn't have '__name__' member."); 1635f757f3fSDimitry Andric PythonString obj_class_name = 1645f757f3fSDimitry Andric obj_class.GetAttributeValue("__name__").AsType<PythonString>(); 1655f757f3fSDimitry Andric 1665f757f3fSDimitry Andric PythonObject object_class_mapping_proxy = 1675f757f3fSDimitry Andric obj_class.GetAttributeValue("__dict__"); 1685f757f3fSDimitry Andric if (!obj_class.HasAttribute("__dict__")) 1695f757f3fSDimitry Andric return create_error( 1705f757f3fSDimitry Andric "Resulting object class doesn't have '__dict__' member."); 1715f757f3fSDimitry Andric 1725f757f3fSDimitry Andric PythonCallable dict_converter = PythonModule::BuiltinsModule() 1735f757f3fSDimitry Andric .ResolveName("dict") 1745f757f3fSDimitry Andric .AsType<PythonCallable>(); 1755f757f3fSDimitry Andric if (!dict_converter.IsAllocated()) 1765f757f3fSDimitry Andric return create_error( 1775f757f3fSDimitry Andric "Python 'builtins' module doesn't have 'dict' class."); 1785f757f3fSDimitry Andric 1795f757f3fSDimitry Andric PythonDictionary object_class_dict = 1805f757f3fSDimitry Andric dict_converter(object_class_mapping_proxy).AsType<PythonDictionary>(); 1815f757f3fSDimitry Andric if (!object_class_dict.IsAllocated()) 1825f757f3fSDimitry Andric return create_error("Coudn't create dictionary from resulting object " 1835f757f3fSDimitry Andric "class mapping proxy object."); 1845f757f3fSDimitry Andric 1855f757f3fSDimitry Andric auto checker_or_err = CheckAbstractMethodImplementation(object_class_dict); 1865f757f3fSDimitry Andric if (!checker_or_err) 1875f757f3fSDimitry Andric return checker_or_err.takeError(); 1885f757f3fSDimitry Andric 1895f757f3fSDimitry Andric for (const auto &method_checker : *checker_or_err) 1905f757f3fSDimitry Andric switch (method_checker.second) { 1915f757f3fSDimitry Andric case AbstractMethodCheckerCases::eNotImplemented: 1925f757f3fSDimitry Andric LLDB_LOG(GetLog(LLDBLog::Script), 1935f757f3fSDimitry Andric "Abstract method {0}.{1} not implemented.", 1945f757f3fSDimitry Andric obj_class_name.GetString(), method_checker.first); 1955f757f3fSDimitry Andric break; 1965f757f3fSDimitry Andric case AbstractMethodCheckerCases::eNotAllocated: 1975f757f3fSDimitry Andric LLDB_LOG(GetLog(LLDBLog::Script), 1985f757f3fSDimitry Andric "Abstract method {0}.{1} not allocated.", 1995f757f3fSDimitry Andric obj_class_name.GetString(), method_checker.first); 2005f757f3fSDimitry Andric break; 2015f757f3fSDimitry Andric case AbstractMethodCheckerCases::eNotCallable: 2025f757f3fSDimitry Andric LLDB_LOG(GetLog(LLDBLog::Script), 2035f757f3fSDimitry Andric "Abstract method {0}.{1} not callable.", 2045f757f3fSDimitry Andric obj_class_name.GetString(), method_checker.first); 2055f757f3fSDimitry Andric break; 2065f757f3fSDimitry Andric case AbstractMethodCheckerCases::eValid: 2075f757f3fSDimitry Andric LLDB_LOG(GetLog(LLDBLog::Script), 2085f757f3fSDimitry Andric "Abstract method {0}.{1} implemented & valid.", 2095f757f3fSDimitry Andric obj_class_name.GetString(), method_checker.first); 2105f757f3fSDimitry Andric break; 2115f757f3fSDimitry Andric } 2125f757f3fSDimitry Andric 2135f757f3fSDimitry Andric for (const auto &method_checker : *checker_or_err) 2145f757f3fSDimitry Andric if (method_checker.second != AbstractMethodCheckerCases::eValid) 2155f757f3fSDimitry Andric return create_error( 2165f757f3fSDimitry Andric llvm::formatv("Abstract method {0}.{1} missing. Enable lldb " 2175f757f3fSDimitry Andric "script log for more details.", 2185f757f3fSDimitry Andric obj_class_name.GetString(), method_checker.first)); 2195f757f3fSDimitry Andric 2205f757f3fSDimitry Andric m_object_instance_sp = StructuredData::GenericSP( 2215f757f3fSDimitry Andric new StructuredPythonObject(std::move(result))); 2225f757f3fSDimitry Andric return m_object_instance_sp; 2235f757f3fSDimitry Andric } 2245f757f3fSDimitry Andric 2255f757f3fSDimitry Andric protected: 2265f757f3fSDimitry Andric template <typename T = StructuredData::ObjectSP> 2275f757f3fSDimitry Andric T ExtractValueFromPythonObject(python::PythonObject &p, Status &error) { 2285f757f3fSDimitry Andric return p.CreateStructuredObject(); 2295f757f3fSDimitry Andric } 2305f757f3fSDimitry Andric 2315f757f3fSDimitry Andric template <typename T = StructuredData::ObjectSP, typename... Args> 2325f757f3fSDimitry Andric T Dispatch(llvm::StringRef method_name, Status &error, Args &&...args) { 2335f757f3fSDimitry Andric using namespace python; 2345f757f3fSDimitry Andric using Locker = ScriptInterpreterPythonImpl::Locker; 2355f757f3fSDimitry Andric 2365f757f3fSDimitry Andric std::string caller_signature = 2375f757f3fSDimitry Andric llvm::Twine(LLVM_PRETTY_FUNCTION + llvm::Twine(" (") + 2385f757f3fSDimitry Andric llvm::Twine(method_name) + llvm::Twine(")")) 2395f757f3fSDimitry Andric .str(); 2405f757f3fSDimitry Andric if (!m_object_instance_sp) 2415f757f3fSDimitry Andric return ErrorWithMessage<T>(caller_signature, "Python object ill-formed", 2425f757f3fSDimitry Andric error); 2435f757f3fSDimitry Andric 2445f757f3fSDimitry Andric Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, 2455f757f3fSDimitry Andric Locker::FreeLock); 2465f757f3fSDimitry Andric 2475f757f3fSDimitry Andric PythonObject implementor(PyRefType::Borrowed, 2485f757f3fSDimitry Andric (PyObject *)m_object_instance_sp->GetValue()); 2495f757f3fSDimitry Andric 2505f757f3fSDimitry Andric if (!implementor.IsAllocated()) 251*0fca6ea1SDimitry Andric return llvm::is_contained(GetAbstractMethods(), method_name) 252*0fca6ea1SDimitry Andric ? ErrorWithMessage<T>(caller_signature, 253*0fca6ea1SDimitry Andric "Python implementor not allocated.", 254*0fca6ea1SDimitry Andric error) 255*0fca6ea1SDimitry Andric : T{}; 2565f757f3fSDimitry Andric 2575f757f3fSDimitry Andric std::tuple<Args...> original_args = std::forward_as_tuple(args...); 2585f757f3fSDimitry Andric auto transformed_args = TransformArgs(original_args); 2595f757f3fSDimitry Andric 2605f757f3fSDimitry Andric llvm::Expected<PythonObject> expected_return_object = 2615f757f3fSDimitry Andric llvm::make_error<llvm::StringError>("Not initialized.", 2625f757f3fSDimitry Andric llvm::inconvertibleErrorCode()); 2635f757f3fSDimitry Andric std::apply( 2645f757f3fSDimitry Andric [&implementor, &method_name, &expected_return_object](auto &&...args) { 2655f757f3fSDimitry Andric llvm::consumeError(expected_return_object.takeError()); 2665f757f3fSDimitry Andric expected_return_object = 2675f757f3fSDimitry Andric implementor.CallMethod(method_name.data(), args...); 2685f757f3fSDimitry Andric }, 2695f757f3fSDimitry Andric transformed_args); 2705f757f3fSDimitry Andric 2715f757f3fSDimitry Andric if (llvm::Error e = expected_return_object.takeError()) { 2725f757f3fSDimitry Andric error.SetErrorString(llvm::toString(std::move(e)).c_str()); 2735f757f3fSDimitry Andric return ErrorWithMessage<T>(caller_signature, 2745f757f3fSDimitry Andric "Python method could not be called.", error); 2755f757f3fSDimitry Andric } 2765f757f3fSDimitry Andric 2775f757f3fSDimitry Andric PythonObject py_return = std::move(expected_return_object.get()); 2785f757f3fSDimitry Andric 2795f757f3fSDimitry Andric // Now that we called the python method with the transformed arguments, 2805f757f3fSDimitry Andric // we need to interate again over both the original and transformed 2815f757f3fSDimitry Andric // parameter pack, and transform back the parameter that were passed in 2825f757f3fSDimitry Andric // the original parameter pack as references or pointers. 2835f757f3fSDimitry Andric if (sizeof...(Args) > 0) 2845f757f3fSDimitry Andric if (!ReassignPtrsOrRefsArgs(original_args, transformed_args)) 2855f757f3fSDimitry Andric return ErrorWithMessage<T>( 2865f757f3fSDimitry Andric caller_signature, 2875f757f3fSDimitry Andric "Couldn't re-assign reference and pointer arguments.", error); 2885f757f3fSDimitry Andric 2895f757f3fSDimitry Andric if (!py_return.IsAllocated()) 2905f757f3fSDimitry Andric return {}; 2915f757f3fSDimitry Andric return ExtractValueFromPythonObject<T>(py_return, error); 2925f757f3fSDimitry Andric } 2935f757f3fSDimitry Andric 2945f757f3fSDimitry Andric template <typename... Args> 2955f757f3fSDimitry Andric Status GetStatusFromMethod(llvm::StringRef method_name, Args &&...args) { 2965f757f3fSDimitry Andric Status error; 2975f757f3fSDimitry Andric Dispatch<Status>(method_name, error, std::forward<Args>(args)...); 2985f757f3fSDimitry Andric 2995f757f3fSDimitry Andric return error; 3005f757f3fSDimitry Andric } 3015f757f3fSDimitry Andric 3025f757f3fSDimitry Andric template <typename T> T Transform(T object) { 3035f757f3fSDimitry Andric // No Transformation for generic usage 3045f757f3fSDimitry Andric return {object}; 3055f757f3fSDimitry Andric } 3065f757f3fSDimitry Andric 3075f757f3fSDimitry Andric python::PythonObject Transform(bool arg) { 3085f757f3fSDimitry Andric // Boolean arguments need to be turned into python objects. 3095f757f3fSDimitry Andric return python::PythonBoolean(arg); 3105f757f3fSDimitry Andric } 3115f757f3fSDimitry Andric 3125f757f3fSDimitry Andric python::PythonObject Transform(Status arg) { 3135f757f3fSDimitry Andric return python::SWIGBridge::ToSWIGWrapper(arg); 3145f757f3fSDimitry Andric } 3155f757f3fSDimitry Andric 3165f757f3fSDimitry Andric python::PythonObject Transform(const StructuredDataImpl &arg) { 3175f757f3fSDimitry Andric return python::SWIGBridge::ToSWIGWrapper(arg); 3185f757f3fSDimitry Andric } 3195f757f3fSDimitry Andric 3205f757f3fSDimitry Andric python::PythonObject Transform(lldb::ExecutionContextRefSP arg) { 3215f757f3fSDimitry Andric return python::SWIGBridge::ToSWIGWrapper(arg); 3225f757f3fSDimitry Andric } 3235f757f3fSDimitry Andric 3245f757f3fSDimitry Andric python::PythonObject Transform(lldb::ProcessSP arg) { 3255f757f3fSDimitry Andric return python::SWIGBridge::ToSWIGWrapper(arg); 3265f757f3fSDimitry Andric } 3275f757f3fSDimitry Andric 328*0fca6ea1SDimitry Andric python::PythonObject Transform(lldb::ThreadPlanSP arg) { 329*0fca6ea1SDimitry Andric return python::SWIGBridge::ToSWIGWrapper(arg); 330*0fca6ea1SDimitry Andric } 331*0fca6ea1SDimitry Andric 3325f757f3fSDimitry Andric python::PythonObject Transform(lldb::ProcessAttachInfoSP arg) { 3335f757f3fSDimitry Andric return python::SWIGBridge::ToSWIGWrapper(arg); 3345f757f3fSDimitry Andric } 3355f757f3fSDimitry Andric 3365f757f3fSDimitry Andric python::PythonObject Transform(lldb::ProcessLaunchInfoSP arg) { 3375f757f3fSDimitry Andric return python::SWIGBridge::ToSWIGWrapper(arg); 3385f757f3fSDimitry Andric } 3395f757f3fSDimitry Andric 340*0fca6ea1SDimitry Andric python::PythonObject Transform(Event *arg) { 341*0fca6ea1SDimitry Andric return python::SWIGBridge::ToSWIGWrapper(arg); 342*0fca6ea1SDimitry Andric } 343*0fca6ea1SDimitry Andric 344*0fca6ea1SDimitry Andric python::PythonObject Transform(lldb::StreamSP arg) { 345*0fca6ea1SDimitry Andric return python::SWIGBridge::ToSWIGWrapper(arg.get()); 346*0fca6ea1SDimitry Andric } 347*0fca6ea1SDimitry Andric 3485f757f3fSDimitry Andric python::PythonObject Transform(lldb::DataExtractorSP arg) { 3495f757f3fSDimitry Andric return python::SWIGBridge::ToSWIGWrapper(arg); 3505f757f3fSDimitry Andric } 3515f757f3fSDimitry Andric 3525f757f3fSDimitry Andric template <typename T, typename U> 3535f757f3fSDimitry Andric void ReverseTransform(T &original_arg, U transformed_arg, Status &error) { 3545f757f3fSDimitry Andric // If U is not a PythonObject, don't touch it! 3555f757f3fSDimitry Andric return; 3565f757f3fSDimitry Andric } 3575f757f3fSDimitry Andric 3585f757f3fSDimitry Andric template <typename T> 3595f757f3fSDimitry Andric void ReverseTransform(T &original_arg, python::PythonObject transformed_arg, 3605f757f3fSDimitry Andric Status &error) { 3615f757f3fSDimitry Andric original_arg = ExtractValueFromPythonObject<T>(transformed_arg, error); 3625f757f3fSDimitry Andric } 3635f757f3fSDimitry Andric 3645f757f3fSDimitry Andric void ReverseTransform(bool &original_arg, 3655f757f3fSDimitry Andric python::PythonObject transformed_arg, Status &error) { 3665f757f3fSDimitry Andric python::PythonBoolean boolean_arg = python::PythonBoolean( 3675f757f3fSDimitry Andric python::PyRefType::Borrowed, transformed_arg.get()); 3685f757f3fSDimitry Andric if (boolean_arg.IsValid()) 3695f757f3fSDimitry Andric original_arg = boolean_arg.GetValue(); 3705f757f3fSDimitry Andric else 3715f757f3fSDimitry Andric error.SetErrorString( 3725f757f3fSDimitry Andric llvm::formatv("{}: Invalid boolean argument.", LLVM_PRETTY_FUNCTION) 3735f757f3fSDimitry Andric .str()); 3745f757f3fSDimitry Andric } 3755f757f3fSDimitry Andric 3765f757f3fSDimitry Andric template <std::size_t... I, typename... Args> 3775f757f3fSDimitry Andric auto TransformTuple(const std::tuple<Args...> &args, 3785f757f3fSDimitry Andric std::index_sequence<I...>) { 3795f757f3fSDimitry Andric return std::make_tuple(Transform(std::get<I>(args))...); 3805f757f3fSDimitry Andric } 3815f757f3fSDimitry Andric 3825f757f3fSDimitry Andric // This will iterate over the Dispatch parameter pack and replace in-place 3835f757f3fSDimitry Andric // every `lldb_private` argument that has a SB counterpart. 3845f757f3fSDimitry Andric template <typename... Args> 3855f757f3fSDimitry Andric auto TransformArgs(const std::tuple<Args...> &args) { 3865f757f3fSDimitry Andric return TransformTuple(args, std::make_index_sequence<sizeof...(Args)>()); 3875f757f3fSDimitry Andric } 3885f757f3fSDimitry Andric 3895f757f3fSDimitry Andric template <typename T, typename U> 3905f757f3fSDimitry Andric void TransformBack(T &original_arg, U transformed_arg, Status &error) { 3915f757f3fSDimitry Andric ReverseTransform(original_arg, transformed_arg, error); 3925f757f3fSDimitry Andric } 3935f757f3fSDimitry Andric 3945f757f3fSDimitry Andric template <std::size_t... I, typename... Ts, typename... Us> 3955f757f3fSDimitry Andric bool ReassignPtrsOrRefsArgs(std::tuple<Ts...> &original_args, 3965f757f3fSDimitry Andric std::tuple<Us...> &transformed_args, 3975f757f3fSDimitry Andric std::index_sequence<I...>) { 3985f757f3fSDimitry Andric Status error; 3995f757f3fSDimitry Andric (TransformBack(std::get<I>(original_args), std::get<I>(transformed_args), 4005f757f3fSDimitry Andric error), 4015f757f3fSDimitry Andric ...); 4025f757f3fSDimitry Andric return error.Success(); 4035f757f3fSDimitry Andric } 4045f757f3fSDimitry Andric 4055f757f3fSDimitry Andric template <typename... Ts, typename... Us> 4065f757f3fSDimitry Andric bool ReassignPtrsOrRefsArgs(std::tuple<Ts...> &original_args, 4075f757f3fSDimitry Andric std::tuple<Us...> &transformed_args) { 4085f757f3fSDimitry Andric if (sizeof...(Ts) != sizeof...(Us)) 4095f757f3fSDimitry Andric return false; 4105f757f3fSDimitry Andric 4115f757f3fSDimitry Andric return ReassignPtrsOrRefsArgs(original_args, transformed_args, 4125f757f3fSDimitry Andric std::make_index_sequence<sizeof...(Ts)>()); 4135f757f3fSDimitry Andric } 4145f757f3fSDimitry Andric 4155f757f3fSDimitry Andric template <typename T, typename... Args> 4165f757f3fSDimitry Andric void FormatArgs(std::string &fmt, T arg, Args... args) const { 4175f757f3fSDimitry Andric FormatArgs(fmt, arg); 4185f757f3fSDimitry Andric FormatArgs(fmt, args...); 4195f757f3fSDimitry Andric } 4205f757f3fSDimitry Andric 4215f757f3fSDimitry Andric template <typename T> void FormatArgs(std::string &fmt, T arg) const { 4225f757f3fSDimitry Andric fmt += python::PythonFormat<T>::format; 4235f757f3fSDimitry Andric } 4245f757f3fSDimitry Andric 4255f757f3fSDimitry Andric void FormatArgs(std::string &fmt) const {} 4265f757f3fSDimitry Andric 4275f757f3fSDimitry Andric // The lifetime is managed by the ScriptInterpreter 4285f757f3fSDimitry Andric ScriptInterpreterPythonImpl &m_interpreter; 4295f757f3fSDimitry Andric }; 4305f757f3fSDimitry Andric 4315f757f3fSDimitry Andric template <> 4325f757f3fSDimitry Andric StructuredData::ArraySP 4335f757f3fSDimitry Andric ScriptedPythonInterface::ExtractValueFromPythonObject<StructuredData::ArraySP>( 4345f757f3fSDimitry Andric python::PythonObject &p, Status &error); 4355f757f3fSDimitry Andric 4365f757f3fSDimitry Andric template <> 4375f757f3fSDimitry Andric StructuredData::DictionarySP 4385f757f3fSDimitry Andric ScriptedPythonInterface::ExtractValueFromPythonObject< 4395f757f3fSDimitry Andric StructuredData::DictionarySP>(python::PythonObject &p, Status &error); 4405f757f3fSDimitry Andric 4415f757f3fSDimitry Andric template <> 4425f757f3fSDimitry Andric Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>( 4435f757f3fSDimitry Andric python::PythonObject &p, Status &error); 4445f757f3fSDimitry Andric 4455f757f3fSDimitry Andric template <> 446*0fca6ea1SDimitry Andric Event *ScriptedPythonInterface::ExtractValueFromPythonObject<Event *>( 447*0fca6ea1SDimitry Andric python::PythonObject &p, Status &error); 448*0fca6ea1SDimitry Andric 449*0fca6ea1SDimitry Andric template <> 450*0fca6ea1SDimitry Andric lldb::StreamSP 451*0fca6ea1SDimitry Andric ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StreamSP>( 452*0fca6ea1SDimitry Andric python::PythonObject &p, Status &error); 453*0fca6ea1SDimitry Andric 454*0fca6ea1SDimitry Andric template <> 4555f757f3fSDimitry Andric lldb::BreakpointSP 4565f757f3fSDimitry Andric ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::BreakpointSP>( 4575f757f3fSDimitry Andric python::PythonObject &p, Status &error); 4585f757f3fSDimitry Andric 4595f757f3fSDimitry Andric template <> 4605f757f3fSDimitry Andric lldb::ProcessAttachInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< 4615f757f3fSDimitry Andric lldb::ProcessAttachInfoSP>(python::PythonObject &p, Status &error); 4625f757f3fSDimitry Andric 4635f757f3fSDimitry Andric template <> 4645f757f3fSDimitry Andric lldb::ProcessLaunchInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< 4655f757f3fSDimitry Andric lldb::ProcessLaunchInfoSP>(python::PythonObject &p, Status &error); 4665f757f3fSDimitry Andric 4675f757f3fSDimitry Andric template <> 4685f757f3fSDimitry Andric lldb::DataExtractorSP 4695f757f3fSDimitry Andric ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>( 4705f757f3fSDimitry Andric python::PythonObject &p, Status &error); 4715f757f3fSDimitry Andric 4725f757f3fSDimitry Andric template <> 4735f757f3fSDimitry Andric std::optional<MemoryRegionInfo> 4745f757f3fSDimitry Andric ScriptedPythonInterface::ExtractValueFromPythonObject< 4755f757f3fSDimitry Andric std::optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error); 4765f757f3fSDimitry Andric 4775f757f3fSDimitry Andric } // namespace lldb_private 4785f757f3fSDimitry Andric 4795f757f3fSDimitry Andric #endif // LLDB_ENABLE_PYTHON 4805f757f3fSDimitry Andric #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H 481