1edb35d95SEugene Zelenko //===-- PythonDataObjects.h--------------------------------------*- C++ -*-===// 22c1f46dcSZachary Turner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 62c1f46dcSZachary Turner // 72c1f46dcSZachary Turner //===----------------------------------------------------------------------===// 82c1f46dcSZachary Turner 9085328eeSLawrence D'Anna // 10085328eeSLawrence D'Anna // !! FIXME FIXME FIXME !! 11085328eeSLawrence D'Anna // 12085328eeSLawrence D'Anna // Python APIs nearly all can return an exception. They do this 13085328eeSLawrence D'Anna // by returning NULL, or -1, or some such value and setting 14085328eeSLawrence D'Anna // the exception state with PyErr_Set*(). Exceptions must be 15085328eeSLawrence D'Anna // handled before further python API functions are called. Failure 16085328eeSLawrence D'Anna // to do so will result in asserts on debug builds of python. 17085328eeSLawrence D'Anna // It will also sometimes, but not usually result in crashes of 18085328eeSLawrence D'Anna // release builds. 19085328eeSLawrence D'Anna // 20085328eeSLawrence D'Anna // Nearly all the code in this header does not handle python exceptions 21085328eeSLawrence D'Anna // correctly. It should all be converted to return Expected<> or 22085328eeSLawrence D'Anna // Error types to capture the exception. 23085328eeSLawrence D'Anna // 24085328eeSLawrence D'Anna // Everything in this file except functions that return Error or 25085328eeSLawrence D'Anna // Expected<> is considered deprecated and should not be 26085328eeSLawrence D'Anna // used in new code. If you need to use it, fix it first. 27085328eeSLawrence D'Anna // 28d3bd5b3dSLawrence D'Anna // 29d3bd5b3dSLawrence D'Anna // TODOs for this file 30d3bd5b3dSLawrence D'Anna // 31d3bd5b3dSLawrence D'Anna // * Make all methods safe for exceptions. 32d3bd5b3dSLawrence D'Anna // 33d3bd5b3dSLawrence D'Anna // * Eliminate method signatures that must translate exceptions into 34d3bd5b3dSLawrence D'Anna // empty objects or NULLs. Almost everything here should return 35d3bd5b3dSLawrence D'Anna // Expected<>. It should be acceptable for certain operations that 36d3bd5b3dSLawrence D'Anna // can never fail to assert instead, such as the creation of 37d3bd5b3dSLawrence D'Anna // PythonString from a string literal. 38d3bd5b3dSLawrence D'Anna // 39e9264b74SKazuaki Ishizaki // * Eliminate Reset(), and make all non-default constructors private. 40d3bd5b3dSLawrence D'Anna // Python objects should be created with Retain<> or Take<>, and they 41d3bd5b3dSLawrence D'Anna // should be assigned with operator= 42d3bd5b3dSLawrence D'Anna // 43d3bd5b3dSLawrence D'Anna // * Eliminate default constructors, make python objects always 44d3bd5b3dSLawrence D'Anna // nonnull, and use optionals where necessary. 45d3bd5b3dSLawrence D'Anna // 46d3bd5b3dSLawrence D'Anna 47085328eeSLawrence D'Anna 482c1f46dcSZachary Turner #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H 492c1f46dcSZachary Turner #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H 502c1f46dcSZachary Turner 5159998b7bSJonas Devlieghere #include "lldb/Host/Config.h" 5259998b7bSJonas Devlieghere 534e26cf2cSJonas Devlieghere #if LLDB_ENABLE_PYTHON 54d68983e3SPavel Labath 5541de9a97SKate Stone // LLDB Python header must be included first 5641de9a97SKate Stone #include "lldb-python.h" 5741de9a97SKate Stone 589c40264fSZachary Turner #include "lldb/Host/File.h" 59f2a8bccfSPavel Labath #include "lldb/Utility/StructuredData.h" 602c1f46dcSZachary Turner 615a72c02bSZachary Turner #include "llvm/ADT/ArrayRef.h" 625a72c02bSZachary Turner 632c1f46dcSZachary Turner namespace lldb_private { 6404edd189SLawrence D'Anna namespace python { 65edb35d95SEugene Zelenko 66085328eeSLawrence D'Anna class PythonObject; 675a72c02bSZachary Turner class PythonBytes; 682c1f46dcSZachary Turner class PythonString; 692c1f46dcSZachary Turner class PythonList; 702c1f46dcSZachary Turner class PythonDictionary; 712c1f46dcSZachary Turner class PythonInteger; 72085328eeSLawrence D'Anna class PythonException; 732c1f46dcSZachary Turner 74*bbef51ebSLawrence D'Anna class GIL { 75*bbef51ebSLawrence D'Anna public: 76*bbef51ebSLawrence D'Anna GIL() { 77*bbef51ebSLawrence D'Anna m_state = PyGILState_Ensure(); 78*bbef51ebSLawrence D'Anna assert(!PyErr_Occurred()); 79*bbef51ebSLawrence D'Anna } 80*bbef51ebSLawrence D'Anna ~GIL() { PyGILState_Release(m_state); } 81*bbef51ebSLawrence D'Anna 82*bbef51ebSLawrence D'Anna protected: 83*bbef51ebSLawrence D'Anna PyGILState_STATE m_state; 84*bbef51ebSLawrence D'Anna }; 85*bbef51ebSLawrence D'Anna 86b9c1b51eSKate Stone class StructuredPythonObject : public StructuredData::Generic { 872c1f46dcSZachary Turner public: 88b9c1b51eSKate Stone StructuredPythonObject() : StructuredData::Generic() {} 892c1f46dcSZachary Turner 90b9c1b51eSKate Stone StructuredPythonObject(void *obj) : StructuredData::Generic(obj) { 912c1f46dcSZachary Turner Py_XINCREF(GetValue()); 922c1f46dcSZachary Turner } 932c1f46dcSZachary Turner 94b9c1b51eSKate Stone ~StructuredPythonObject() override { 952c1f46dcSZachary Turner if (Py_IsInitialized()) 962c1f46dcSZachary Turner Py_XDECREF(GetValue()); 972c1f46dcSZachary Turner SetValue(nullptr); 982c1f46dcSZachary Turner } 992c1f46dcSZachary Turner 100b9c1b51eSKate Stone bool IsValid() const override { return GetValue() && GetValue() != Py_None; } 1012c1f46dcSZachary Turner 1022783d817SJonas Devlieghere void Serialize(llvm::json::OStream &s) const override; 1032c1f46dcSZachary Turner 1042c1f46dcSZachary Turner private: 105eaebcbc6SKonrad Kleine StructuredPythonObject(const StructuredPythonObject &) = delete; 106eaebcbc6SKonrad Kleine const StructuredPythonObject & 107eaebcbc6SKonrad Kleine operator=(const StructuredPythonObject &) = delete; 1082c1f46dcSZachary Turner }; 1092c1f46dcSZachary Turner 110b9c1b51eSKate Stone enum class PyObjectType { 1112c1f46dcSZachary Turner Unknown, 1122c1f46dcSZachary Turner None, 113b81d715cSTatyana Krasnukha Boolean, 1142c1f46dcSZachary Turner Integer, 1152c1f46dcSZachary Turner Dictionary, 1162c1f46dcSZachary Turner List, 1179c40264fSZachary Turner String, 1185a72c02bSZachary Turner Bytes, 119f9d6d204SZachary Turner ByteArray, 1207841efbbSZachary Turner Module, 121a1405147SZachary Turner Callable, 122a1405147SZachary Turner Tuple, 1239c40264fSZachary Turner File 1242c1f46dcSZachary Turner }; 1252c1f46dcSZachary Turner 126b9c1b51eSKate Stone enum class PyRefType { 127f8b22f8fSZachary Turner Borrowed, // We are not given ownership of the incoming PyObject. 128f8b22f8fSZachary Turner // We cannot safely hold it without calling Py_INCREF. 129f8b22f8fSZachary Turner Owned // We have ownership of the incoming PyObject. We should 130f8b22f8fSZachary Turner // not call Py_INCREF. 131f8b22f8fSZachary Turner }; 132f8b22f8fSZachary Turner 133085328eeSLawrence D'Anna 134085328eeSLawrence D'Anna // Take a reference that you already own, and turn it into 135085328eeSLawrence D'Anna // a PythonObject. 136085328eeSLawrence D'Anna // 137085328eeSLawrence D'Anna // Most python API methods will return a +1 reference 138085328eeSLawrence D'Anna // if they succeed or NULL if and only if 139085328eeSLawrence D'Anna // they set an exception. Use this to collect such return 140085328eeSLawrence D'Anna // values, after checking for NULL. 141085328eeSLawrence D'Anna // 142085328eeSLawrence D'Anna // If T is not just PythonObject, then obj must be already be 143085328eeSLawrence D'Anna // checked to be of the correct type. 144085328eeSLawrence D'Anna template <typename T> T Take(PyObject *obj) { 145085328eeSLawrence D'Anna assert(obj); 146085328eeSLawrence D'Anna assert(!PyErr_Occurred()); 147085328eeSLawrence D'Anna T thing(PyRefType::Owned, obj); 148085328eeSLawrence D'Anna assert(thing.IsValid()); 1491dfb1a85SPavel Labath return thing; 150085328eeSLawrence D'Anna } 151085328eeSLawrence D'Anna 152085328eeSLawrence D'Anna // Retain a reference you have borrowed, and turn it into 153085328eeSLawrence D'Anna // a PythonObject. 154085328eeSLawrence D'Anna // 155085328eeSLawrence D'Anna // A minority of python APIs return a borrowed reference 156085328eeSLawrence D'Anna // instead of a +1. They will also return NULL if and only 157085328eeSLawrence D'Anna // if they set an exception. Use this to collect such return 158085328eeSLawrence D'Anna // values, after checking for NULL. 159085328eeSLawrence D'Anna // 160085328eeSLawrence D'Anna // If T is not just PythonObject, then obj must be already be 161085328eeSLawrence D'Anna // checked to be of the correct type. 162085328eeSLawrence D'Anna template <typename T> T Retain(PyObject *obj) { 163085328eeSLawrence D'Anna assert(obj); 164085328eeSLawrence D'Anna assert(!PyErr_Occurred()); 165085328eeSLawrence D'Anna T thing(PyRefType::Borrowed, obj); 166085328eeSLawrence D'Anna assert(thing.IsValid()); 1671dfb1a85SPavel Labath return thing; 168085328eeSLawrence D'Anna } 169085328eeSLawrence D'Anna 170722b6189SLawrence D'Anna // This class can be used like a utility function to convert from 171722b6189SLawrence D'Anna // a llvm-friendly Twine into a null-terminated const char *, 172722b6189SLawrence D'Anna // which is the form python C APIs want their strings in. 173722b6189SLawrence D'Anna // 174722b6189SLawrence D'Anna // Example: 175722b6189SLawrence D'Anna // const llvm::Twine &some_twine; 176722b6189SLawrence D'Anna // PyFoo_Bar(x, y, z, NullTerminated(some_twine)); 177722b6189SLawrence D'Anna // 178722b6189SLawrence D'Anna // Why a class instead of a function? If the twine isn't already null 179722b6189SLawrence D'Anna // terminated, it will need a temporary buffer to copy the string 180722b6189SLawrence D'Anna // into. We need that buffer to stick around for the lifetime of the 181722b6189SLawrence D'Anna // statement. 182722b6189SLawrence D'Anna class NullTerminated { 183722b6189SLawrence D'Anna const char *str; 184722b6189SLawrence D'Anna llvm::SmallString<32> storage; 185722b6189SLawrence D'Anna 186722b6189SLawrence D'Anna public: 187722b6189SLawrence D'Anna NullTerminated(const llvm::Twine &twine) { 188722b6189SLawrence D'Anna llvm::StringRef ref = twine.toNullTerminatedStringRef(storage); 189722b6189SLawrence D'Anna str = ref.begin(); 190722b6189SLawrence D'Anna } 191722b6189SLawrence D'Anna operator const char *() { return str; } 192722b6189SLawrence D'Anna }; 193722b6189SLawrence D'Anna 19404edd189SLawrence D'Anna inline llvm::Error nullDeref() { 19504edd189SLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 19604edd189SLawrence D'Anna "A NULL PyObject* was dereferenced"); 19704edd189SLawrence D'Anna } 19804edd189SLawrence D'Anna 19904edd189SLawrence D'Anna inline llvm::Error exception(const char *s = nullptr) { 20004edd189SLawrence D'Anna return llvm::make_error<PythonException>(s); 20104edd189SLawrence D'Anna } 20204edd189SLawrence D'Anna 20304edd189SLawrence D'Anna inline llvm::Error keyError() { 20404edd189SLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 20504edd189SLawrence D'Anna "key not in dict"); 20604edd189SLawrence D'Anna } 207085328eeSLawrence D'Anna 2086a93a12aSLawrence D'Anna #if PY_MAJOR_VERSION < 3 2096a93a12aSLawrence D'Anna // The python 2 API declares some arguments as char* that should 2106a93a12aSLawrence D'Anna // be const char *, but it doesn't actually modify them. 2116a93a12aSLawrence D'Anna inline char *py2_const_cast(const char *s) { return const_cast<char *>(s); } 2126a93a12aSLawrence D'Anna #else 2136a93a12aSLawrence D'Anna inline const char *py2_const_cast(const char *s) { return s; } 2146a93a12aSLawrence D'Anna #endif 2156a93a12aSLawrence D'Anna 216b9c1b51eSKate Stone enum class PyInitialValue { Invalid, Empty }; 217f8b22f8fSZachary Turner 218085328eeSLawrence D'Anna template <typename T, typename Enable = void> struct PythonFormat; 219085328eeSLawrence D'Anna 220085328eeSLawrence D'Anna template <> struct PythonFormat<unsigned long long> { 221085328eeSLawrence D'Anna static constexpr char format = 'K'; 222085328eeSLawrence D'Anna static auto get(unsigned long long value) { return value; } 223085328eeSLawrence D'Anna }; 224085328eeSLawrence D'Anna 225085328eeSLawrence D'Anna template <> struct PythonFormat<long long> { 226085328eeSLawrence D'Anna static constexpr char format = 'L'; 227085328eeSLawrence D'Anna static auto get(long long value) { return value; } 228085328eeSLawrence D'Anna }; 229085328eeSLawrence D'Anna 23004edd189SLawrence D'Anna template <> struct PythonFormat<PyObject *> { 23104edd189SLawrence D'Anna static constexpr char format = 'O'; 23204edd189SLawrence D'Anna static auto get(PyObject *value) { return value; } 23304edd189SLawrence D'Anna }; 23404edd189SLawrence D'Anna 235085328eeSLawrence D'Anna template <typename T> 236085328eeSLawrence D'Anna struct PythonFormat< 237085328eeSLawrence D'Anna T, typename std::enable_if<std::is_base_of<PythonObject, T>::value>::type> { 238085328eeSLawrence D'Anna static constexpr char format = 'O'; 239085328eeSLawrence D'Anna static auto get(const T &value) { return value.get(); } 240085328eeSLawrence D'Anna }; 241085328eeSLawrence D'Anna 242b9c1b51eSKate Stone class PythonObject { 2432c1f46dcSZachary Turner public: 244fd2433e1SJonas Devlieghere PythonObject() = default; 2452c1f46dcSZachary Turner 24604edd189SLawrence D'Anna PythonObject(PyRefType type, PyObject *py_obj) { 24704edd189SLawrence D'Anna m_py_obj = py_obj; 24804edd189SLawrence D'Anna // If this is a borrowed reference, we need to convert it to 24904edd189SLawrence D'Anna // an owned reference by incrementing it. If it is an owned 25004edd189SLawrence D'Anna // reference (for example the caller allocated it with PyDict_New() 25104edd189SLawrence D'Anna // then we must *not* increment it. 25204edd189SLawrence D'Anna if (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed) 25304edd189SLawrence D'Anna Py_XINCREF(m_py_obj); 2542c1f46dcSZachary Turner } 2552c1f46dcSZachary Turner 25603819d1cSLawrence D'Anna PythonObject(const PythonObject &rhs) 25703819d1cSLawrence D'Anna : PythonObject(PyRefType::Borrowed, rhs.m_py_obj) {} 2582c1f46dcSZachary Turner 259085328eeSLawrence D'Anna PythonObject(PythonObject &&rhs) { 260085328eeSLawrence D'Anna m_py_obj = rhs.m_py_obj; 261085328eeSLawrence D'Anna rhs.m_py_obj = nullptr; 262085328eeSLawrence D'Anna } 263085328eeSLawrence D'Anna 264d3bd5b3dSLawrence D'Anna ~PythonObject() { Reset(); } 2652c1f46dcSZachary Turner 266b9c1b51eSKate Stone void Reset() { 267085328eeSLawrence D'Anna if (m_py_obj && Py_IsInitialized()) 268085328eeSLawrence D'Anna Py_DECREF(m_py_obj); 269f8b22f8fSZachary Turner m_py_obj = nullptr; 2702c1f46dcSZachary Turner } 271f8b22f8fSZachary Turner 272b9c1b51eSKate Stone void Dump() const { 2732c1f46dcSZachary Turner if (m_py_obj) 2742c1f46dcSZachary Turner _PyObject_Dump(m_py_obj); 2752c1f46dcSZachary Turner else 2762c1f46dcSZachary Turner puts("NULL"); 2772c1f46dcSZachary Turner } 2782c1f46dcSZachary Turner 279b9c1b51eSKate Stone void Dump(Stream &strm) const; 2802c1f46dcSZachary Turner 281b9c1b51eSKate Stone PyObject *get() const { return m_py_obj; } 2822c1f46dcSZachary Turner 283b9c1b51eSKate Stone PyObject *release() { 28460c24f70SZachary Turner PyObject *result = m_py_obj; 28560c24f70SZachary Turner m_py_obj = nullptr; 28660c24f70SZachary Turner return result; 28760c24f70SZachary Turner } 28860c24f70SZachary Turner 28903819d1cSLawrence D'Anna PythonObject &operator=(PythonObject other) { 290085328eeSLawrence D'Anna Reset(); 29103819d1cSLawrence D'Anna m_py_obj = std::exchange(other.m_py_obj, nullptr); 292085328eeSLawrence D'Anna return *this; 293085328eeSLawrence D'Anna } 294085328eeSLawrence D'Anna 295b9c1b51eSKate Stone PyObjectType GetObjectType() const; 2967841efbbSZachary Turner 297b9c1b51eSKate Stone PythonString Repr() const; 2987841efbbSZachary Turner 299b9c1b51eSKate Stone PythonString Str() const; 3007841efbbSZachary Turner 301b9c1b51eSKate Stone static PythonObject ResolveNameWithDictionary(llvm::StringRef name, 302b9c1b51eSKate Stone const PythonDictionary &dict); 3037841efbbSZachary Turner 304b58fb2f4SZachary Turner template <typename T> 305b9c1b51eSKate Stone static T ResolveNameWithDictionary(llvm::StringRef name, 306b9c1b51eSKate Stone const PythonDictionary &dict) { 307b58fb2f4SZachary Turner return ResolveNameWithDictionary(name, dict).AsType<T>(); 308b58fb2f4SZachary Turner } 309b58fb2f4SZachary Turner 310b9c1b51eSKate Stone PythonObject ResolveName(llvm::StringRef name) const; 3117841efbbSZachary Turner 312b9c1b51eSKate Stone template <typename T> T ResolveName(llvm::StringRef name) const { 313b58fb2f4SZachary Turner return ResolveName(name).AsType<T>(); 314b58fb2f4SZachary Turner } 315b58fb2f4SZachary Turner 316b9c1b51eSKate Stone bool HasAttribute(llvm::StringRef attribute) const; 3179c40264fSZachary Turner 318b9c1b51eSKate Stone PythonObject GetAttributeValue(llvm::StringRef attribute) const; 3197d6d218eSZachary Turner 320085328eeSLawrence D'Anna bool IsNone() const { return m_py_obj == Py_None; } 321f8b22f8fSZachary Turner 322085328eeSLawrence D'Anna bool IsValid() const { return m_py_obj != nullptr; } 323f8b22f8fSZachary Turner 324085328eeSLawrence D'Anna bool IsAllocated() const { return IsValid() && !IsNone(); } 325085328eeSLawrence D'Anna 326085328eeSLawrence D'Anna explicit operator bool() const { return IsValid() && !IsNone(); } 3272c1f46dcSZachary Turner 328b9c1b51eSKate Stone template <typename T> T AsType() const { 3297d6d218eSZachary Turner if (!T::Check(m_py_obj)) 3307d6d218eSZachary Turner return T(); 3317d6d218eSZachary Turner return T(PyRefType::Borrowed, m_py_obj); 3327d6d218eSZachary Turner } 3337d6d218eSZachary Turner 334b9c1b51eSKate Stone StructuredData::ObjectSP CreateStructuredObject() const; 3352c1f46dcSZachary Turner 336085328eeSLawrence D'Anna template <typename... T> 337085328eeSLawrence D'Anna llvm::Expected<PythonObject> CallMethod(const char *name, 338085328eeSLawrence D'Anna const T &... t) const { 339085328eeSLawrence D'Anna const char format[] = {'(', PythonFormat<T>::format..., ')', 0}; 340085328eeSLawrence D'Anna PyObject *obj = 341c86a6acaSLawrence D'Anna PyObject_CallMethod(m_py_obj, py2_const_cast(name), 342c86a6acaSLawrence D'Anna py2_const_cast(format), PythonFormat<T>::get(t)...); 343c86a6acaSLawrence D'Anna if (!obj) 344c86a6acaSLawrence D'Anna return exception(); 345c86a6acaSLawrence D'Anna return python::Take<PythonObject>(obj); 346c86a6acaSLawrence D'Anna } 347c86a6acaSLawrence D'Anna 348c86a6acaSLawrence D'Anna template <typename... T> 349c86a6acaSLawrence D'Anna llvm::Expected<PythonObject> Call(const T &... t) const { 350c86a6acaSLawrence D'Anna const char format[] = {'(', PythonFormat<T>::format..., ')', 0}; 351c86a6acaSLawrence D'Anna PyObject *obj = PyObject_CallFunction(m_py_obj, py2_const_cast(format), 352c86a6acaSLawrence D'Anna PythonFormat<T>::get(t)...); 353085328eeSLawrence D'Anna if (!obj) 354085328eeSLawrence D'Anna return exception(); 355085328eeSLawrence D'Anna return python::Take<PythonObject>(obj); 356085328eeSLawrence D'Anna } 357085328eeSLawrence D'Anna 358722b6189SLawrence D'Anna llvm::Expected<PythonObject> GetAttribute(const llvm::Twine &name) const { 359085328eeSLawrence D'Anna if (!m_py_obj) 360085328eeSLawrence D'Anna return nullDeref(); 361722b6189SLawrence D'Anna PyObject *obj = PyObject_GetAttrString(m_py_obj, NullTerminated(name)); 362085328eeSLawrence D'Anna if (!obj) 363085328eeSLawrence D'Anna return exception(); 364085328eeSLawrence D'Anna return python::Take<PythonObject>(obj); 365085328eeSLawrence D'Anna } 366085328eeSLawrence D'Anna 367085328eeSLawrence D'Anna llvm::Expected<bool> IsTrue() { 368085328eeSLawrence D'Anna if (!m_py_obj) 369085328eeSLawrence D'Anna return nullDeref(); 370085328eeSLawrence D'Anna int r = PyObject_IsTrue(m_py_obj); 371085328eeSLawrence D'Anna if (r < 0) 372085328eeSLawrence D'Anna return exception(); 373085328eeSLawrence D'Anna return !!r; 374085328eeSLawrence D'Anna } 375085328eeSLawrence D'Anna 37652712d3fSLawrence D'Anna llvm::Expected<long long> AsLongLong() const; 37752712d3fSLawrence D'Anna 37852712d3fSLawrence D'Anna llvm::Expected<long long> AsUnsignedLongLong() const; 37952712d3fSLawrence D'Anna 38052712d3fSLawrence D'Anna // wraps on overflow, instead of raising an error. 38152712d3fSLawrence D'Anna llvm::Expected<unsigned long long> AsModuloUnsignedLongLong() const; 382085328eeSLawrence D'Anna 383085328eeSLawrence D'Anna llvm::Expected<bool> IsInstance(const PythonObject &cls) { 384085328eeSLawrence D'Anna if (!m_py_obj || !cls.IsValid()) 385085328eeSLawrence D'Anna return nullDeref(); 386085328eeSLawrence D'Anna int r = PyObject_IsInstance(m_py_obj, cls.get()); 387085328eeSLawrence D'Anna if (r < 0) 388085328eeSLawrence D'Anna return exception(); 389085328eeSLawrence D'Anna return !!r; 390085328eeSLawrence D'Anna } 391085328eeSLawrence D'Anna 392085328eeSLawrence D'Anna protected: 3939494c510SJonas Devlieghere PyObject *m_py_obj = nullptr; 3942c1f46dcSZachary Turner }; 3952c1f46dcSZachary Turner 396085328eeSLawrence D'Anna 397085328eeSLawrence D'Anna // This is why C++ needs monads. 398085328eeSLawrence D'Anna template <typename T> llvm::Expected<T> As(llvm::Expected<PythonObject> &&obj) { 399085328eeSLawrence D'Anna if (!obj) 400085328eeSLawrence D'Anna return obj.takeError(); 401085328eeSLawrence D'Anna if (!T::Check(obj.get().get())) 402085328eeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 403085328eeSLawrence D'Anna "type error"); 404085328eeSLawrence D'Anna return T(PyRefType::Borrowed, std::move(obj.get().get())); 405085328eeSLawrence D'Anna } 406085328eeSLawrence D'Anna 407085328eeSLawrence D'Anna template <> llvm::Expected<bool> As<bool>(llvm::Expected<PythonObject> &&obj); 408085328eeSLawrence D'Anna 409085328eeSLawrence D'Anna template <> 410085328eeSLawrence D'Anna llvm::Expected<long long> As<long long>(llvm::Expected<PythonObject> &&obj); 411085328eeSLawrence D'Anna 412c86a6acaSLawrence D'Anna template <> 41352712d3fSLawrence D'Anna llvm::Expected<unsigned long long> 41452712d3fSLawrence D'Anna As<unsigned long long>(llvm::Expected<PythonObject> &&obj); 41552712d3fSLawrence D'Anna 41652712d3fSLawrence D'Anna template <> 417c86a6acaSLawrence D'Anna llvm::Expected<std::string> As<std::string>(llvm::Expected<PythonObject> &&obj); 418c86a6acaSLawrence D'Anna 419085328eeSLawrence D'Anna 420d3bd5b3dSLawrence D'Anna template <class T> class TypedPythonObject : public PythonObject { 4215a72c02bSZachary Turner public: 422d3bd5b3dSLawrence D'Anna // override to perform implicit type conversions on Reset 423d3bd5b3dSLawrence D'Anna // This can be eliminated once we drop python 2 support. 424d3bd5b3dSLawrence D'Anna static void Convert(PyRefType &type, PyObject *&py_obj) {} 425d3bd5b3dSLawrence D'Anna 426722b6189SLawrence D'Anna TypedPythonObject(PyRefType type, PyObject *py_obj) { 427d3bd5b3dSLawrence D'Anna if (!py_obj) 428d3bd5b3dSLawrence D'Anna return; 429d3bd5b3dSLawrence D'Anna T::Convert(type, py_obj); 430d3bd5b3dSLawrence D'Anna if (T::Check(py_obj)) 43104edd189SLawrence D'Anna PythonObject::operator=(PythonObject(type, py_obj)); 432d3bd5b3dSLawrence D'Anna else if (type == PyRefType::Owned) 433d3bd5b3dSLawrence D'Anna Py_DECREF(py_obj); 434d3bd5b3dSLawrence D'Anna } 435d3bd5b3dSLawrence D'Anna 436fd2433e1SJonas Devlieghere TypedPythonObject() = default; 437d3bd5b3dSLawrence D'Anna }; 438d3bd5b3dSLawrence D'Anna 439d3bd5b3dSLawrence D'Anna class PythonBytes : public TypedPythonObject<PythonBytes> { 440d3bd5b3dSLawrence D'Anna public: 441d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 4425a72c02bSZachary Turner explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes); 4435a72c02bSZachary Turner PythonBytes(const uint8_t *bytes, size_t length); 4445a72c02bSZachary Turner 445b9c1b51eSKate Stone static bool Check(PyObject *py_obj); 4465a72c02bSZachary Turner 447b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> GetBytes() const; 4485a72c02bSZachary Turner 449b9c1b51eSKate Stone size_t GetSize() const; 4505a72c02bSZachary Turner 451b9c1b51eSKate Stone void SetBytes(llvm::ArrayRef<uint8_t> stringbytes); 4525a72c02bSZachary Turner 453b9c1b51eSKate Stone StructuredData::StringSP CreateStructuredString() const; 4545a72c02bSZachary Turner }; 4555a72c02bSZachary Turner 456d3bd5b3dSLawrence D'Anna class PythonByteArray : public TypedPythonObject<PythonByteArray> { 457f9d6d204SZachary Turner public: 458d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 459f9d6d204SZachary Turner explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes); 460f9d6d204SZachary Turner PythonByteArray(const uint8_t *bytes, size_t length); 461f9d6d204SZachary Turner PythonByteArray(const PythonBytes &object); 462f9d6d204SZachary Turner 463b9c1b51eSKate Stone static bool Check(PyObject *py_obj); 464f9d6d204SZachary Turner 465b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> GetBytes() const; 466f9d6d204SZachary Turner 467b9c1b51eSKate Stone size_t GetSize() const; 468f9d6d204SZachary Turner 469b9c1b51eSKate Stone void SetBytes(llvm::ArrayRef<uint8_t> stringbytes); 470f9d6d204SZachary Turner 471b9c1b51eSKate Stone StructuredData::StringSP CreateStructuredString() const; 472f9d6d204SZachary Turner }; 473f9d6d204SZachary Turner 474d3bd5b3dSLawrence D'Anna class PythonString : public TypedPythonObject<PythonString> { 4752c1f46dcSZachary Turner public: 476d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 477085328eeSLawrence D'Anna static llvm::Expected<PythonString> FromUTF8(llvm::StringRef string); 478085328eeSLawrence D'Anna 479d3bd5b3dSLawrence D'Anna PythonString() : TypedPythonObject() {} // MSVC requires this for some reason 480edb35d95SEugene Zelenko 481d3bd5b3dSLawrence D'Anna explicit PythonString(llvm::StringRef string); // safe, null on error 4822c1f46dcSZachary Turner 48322c8efcdSZachary Turner static bool Check(PyObject *py_obj); 484d3bd5b3dSLawrence D'Anna static void Convert(PyRefType &type, PyObject *&py_obj); 4852c1f46dcSZachary Turner 486085328eeSLawrence D'Anna llvm::StringRef GetString() const; // safe, empty string on error 487085328eeSLawrence D'Anna 488085328eeSLawrence D'Anna llvm::Expected<llvm::StringRef> AsUTF8() const; 4892c1f46dcSZachary Turner 490b9c1b51eSKate Stone size_t GetSize() const; 4912c1f46dcSZachary Turner 492085328eeSLawrence D'Anna void SetString(llvm::StringRef string); // safe, null on error 4932c1f46dcSZachary Turner 4942c1f46dcSZachary Turner StructuredData::StringSP CreateStructuredString() const; 4952c1f46dcSZachary Turner }; 4962c1f46dcSZachary Turner 497d3bd5b3dSLawrence D'Anna class PythonInteger : public TypedPythonObject<PythonInteger> { 4982c1f46dcSZachary Turner public: 499d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 500edb35d95SEugene Zelenko 501d3bd5b3dSLawrence D'Anna PythonInteger() : TypedPythonObject() {} // MSVC requires this for some reason 502d3bd5b3dSLawrence D'Anna 503d3bd5b3dSLawrence D'Anna explicit PythonInteger(int64_t value); 5042c1f46dcSZachary Turner 50522c8efcdSZachary Turner static bool Check(PyObject *py_obj); 506d3bd5b3dSLawrence D'Anna static void Convert(PyRefType &type, PyObject *&py_obj); 5072c1f46dcSZachary Turner 508b9c1b51eSKate Stone void SetInteger(int64_t value); 5092c1f46dcSZachary Turner 5102c1f46dcSZachary Turner StructuredData::IntegerSP CreateStructuredInteger() const; 5112c1f46dcSZachary Turner }; 5122c1f46dcSZachary Turner 513d3bd5b3dSLawrence D'Anna class PythonBoolean : public TypedPythonObject<PythonBoolean> { 514b81d715cSTatyana Krasnukha public: 515d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 516b81d715cSTatyana Krasnukha 517d3bd5b3dSLawrence D'Anna explicit PythonBoolean(bool value); 518b81d715cSTatyana Krasnukha 519b81d715cSTatyana Krasnukha static bool Check(PyObject *py_obj); 520b81d715cSTatyana Krasnukha 521b81d715cSTatyana Krasnukha bool GetValue() const; 522b81d715cSTatyana Krasnukha 523b81d715cSTatyana Krasnukha void SetValue(bool value); 524b81d715cSTatyana Krasnukha 525b81d715cSTatyana Krasnukha StructuredData::BooleanSP CreateStructuredBoolean() const; 526b81d715cSTatyana Krasnukha }; 527b81d715cSTatyana Krasnukha 528d3bd5b3dSLawrence D'Anna class PythonList : public TypedPythonObject<PythonList> { 5292c1f46dcSZachary Turner public: 530d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 531d3bd5b3dSLawrence D'Anna 532d3bd5b3dSLawrence D'Anna PythonList() : TypedPythonObject() {} // MSVC requires this for some reason 533d3bd5b3dSLawrence D'Anna 53487f47729SZachary Turner explicit PythonList(PyInitialValue value); 53587f47729SZachary Turner explicit PythonList(int list_size); 5362c1f46dcSZachary Turner 53722c8efcdSZachary Turner static bool Check(PyObject *py_obj); 53822c8efcdSZachary Turner 5392c1f46dcSZachary Turner uint32_t GetSize() const; 5402c1f46dcSZachary Turner 5412c1f46dcSZachary Turner PythonObject GetItemAtIndex(uint32_t index) const; 5422c1f46dcSZachary Turner 543f8b22f8fSZachary Turner void SetItemAtIndex(uint32_t index, const PythonObject &object); 5442c1f46dcSZachary Turner 545f8b22f8fSZachary Turner void AppendItem(const PythonObject &object); 5462c1f46dcSZachary Turner 5472c1f46dcSZachary Turner StructuredData::ArraySP CreateStructuredArray() const; 5482c1f46dcSZachary Turner }; 5492c1f46dcSZachary Turner 550d3bd5b3dSLawrence D'Anna class PythonTuple : public TypedPythonObject<PythonTuple> { 551a1405147SZachary Turner public: 552d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 553d3bd5b3dSLawrence D'Anna 554a1405147SZachary Turner explicit PythonTuple(PyInitialValue value); 555a1405147SZachary Turner explicit PythonTuple(int tuple_size); 556a1405147SZachary Turner PythonTuple(std::initializer_list<PythonObject> objects); 557a1405147SZachary Turner PythonTuple(std::initializer_list<PyObject *> objects); 558a1405147SZachary Turner 559a1405147SZachary Turner static bool Check(PyObject *py_obj); 560a1405147SZachary Turner 561a1405147SZachary Turner uint32_t GetSize() const; 562a1405147SZachary Turner 563a1405147SZachary Turner PythonObject GetItemAtIndex(uint32_t index) const; 564a1405147SZachary Turner 565a1405147SZachary Turner void SetItemAtIndex(uint32_t index, const PythonObject &object); 566a1405147SZachary Turner 567a1405147SZachary Turner StructuredData::ArraySP CreateStructuredArray() const; 568a1405147SZachary Turner }; 569a1405147SZachary Turner 570d3bd5b3dSLawrence D'Anna class PythonDictionary : public TypedPythonObject<PythonDictionary> { 5712c1f46dcSZachary Turner public: 572d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 573edb35d95SEugene Zelenko 574d3bd5b3dSLawrence D'Anna PythonDictionary() : TypedPythonObject() {} // MSVC requires this for some reason 575d3bd5b3dSLawrence D'Anna 576d3bd5b3dSLawrence D'Anna explicit PythonDictionary(PyInitialValue value); 5772c1f46dcSZachary Turner 57822c8efcdSZachary Turner static bool Check(PyObject *py_obj); 57922c8efcdSZachary Turner 5802c1f46dcSZachary Turner uint32_t GetSize() const; 5812c1f46dcSZachary Turner 582f8b22f8fSZachary Turner PythonList GetKeys() const; 5832c1f46dcSZachary Turner 584c86a6acaSLawrence D'Anna PythonObject GetItemForKey(const PythonObject &key) const; // DEPRECATED 585c86a6acaSLawrence D'Anna void SetItemForKey(const PythonObject &key, 586c86a6acaSLawrence D'Anna const PythonObject &value); // DEPRECATED 587c86a6acaSLawrence D'Anna 588c86a6acaSLawrence D'Anna llvm::Expected<PythonObject> GetItem(const PythonObject &key) const; 589722b6189SLawrence D'Anna llvm::Expected<PythonObject> GetItem(const llvm::Twine &key) const; 590c86a6acaSLawrence D'Anna llvm::Error SetItem(const PythonObject &key, const PythonObject &value) const; 591722b6189SLawrence D'Anna llvm::Error SetItem(const llvm::Twine &key, const PythonObject &value) const; 5922c1f46dcSZachary Turner 5932c1f46dcSZachary Turner StructuredData::DictionarySP CreateStructuredDictionary() const; 5942c1f46dcSZachary Turner }; 59587f47729SZachary Turner 596d3bd5b3dSLawrence D'Anna class PythonModule : public TypedPythonObject<PythonModule> { 5977841efbbSZachary Turner public: 598d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 5997841efbbSZachary Turner 6007841efbbSZachary Turner static bool Check(PyObject *py_obj); 6017841efbbSZachary Turner 602b9c1b51eSKate Stone static PythonModule BuiltinsModule(); 603a1405147SZachary Turner 604b9c1b51eSKate Stone static PythonModule MainModule(); 605a1405147SZachary Turner 606b9c1b51eSKate Stone static PythonModule AddModule(llvm::StringRef module); 6077841efbbSZachary Turner 608085328eeSLawrence D'Anna // safe, returns invalid on error; 609085328eeSLawrence D'Anna static PythonModule ImportModule(llvm::StringRef name) { 610adcd0268SBenjamin Kramer std::string s = std::string(name); 611085328eeSLawrence D'Anna auto mod = Import(s.c_str()); 612085328eeSLawrence D'Anna if (!mod) { 613085328eeSLawrence D'Anna llvm::consumeError(mod.takeError()); 614085328eeSLawrence D'Anna return PythonModule(); 615085328eeSLawrence D'Anna } 616085328eeSLawrence D'Anna return std::move(mod.get()); 617085328eeSLawrence D'Anna } 618085328eeSLawrence D'Anna 619722b6189SLawrence D'Anna static llvm::Expected<PythonModule> Import(const llvm::Twine &name); 620085328eeSLawrence D'Anna 621722b6189SLawrence D'Anna llvm::Expected<PythonObject> Get(const llvm::Twine &name); 6222419f1d5SZachary Turner 6237841efbbSZachary Turner PythonDictionary GetDictionary() const; 6247841efbbSZachary Turner }; 6257841efbbSZachary Turner 626d3bd5b3dSLawrence D'Anna class PythonCallable : public TypedPythonObject<PythonCallable> { 627a1405147SZachary Turner public: 628d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 629d3bd5b3dSLawrence D'Anna 630b58fb2f4SZachary Turner struct ArgInfo { 6312386537cSLawrence D'Anna /* the largest number of positional arguments this callable 6322386537cSLawrence D'Anna * can accept, or UNBOUNDED, ie UINT_MAX if it's a varargs 6332386537cSLawrence D'Anna * function and can accept an arbitrary number */ 6342386537cSLawrence D'Anna unsigned max_positional_args; 6352386537cSLawrence D'Anna static constexpr unsigned UNBOUNDED = UINT_MAX; // FIXME c++17 inline 636b58fb2f4SZachary Turner }; 637b58fb2f4SZachary Turner 638b9c1b51eSKate Stone static bool Check(PyObject *py_obj); 639a1405147SZachary Turner 640c86a6acaSLawrence D'Anna llvm::Expected<ArgInfo> GetArgInfo() const; 641c86a6acaSLawrence D'Anna 642b9c1b51eSKate Stone PythonObject operator()(); 643a1405147SZachary Turner 644b9c1b51eSKate Stone PythonObject operator()(std::initializer_list<PyObject *> args); 645a1405147SZachary Turner 646b9c1b51eSKate Stone PythonObject operator()(std::initializer_list<PythonObject> args); 647b58fb2f4SZachary Turner 648b58fb2f4SZachary Turner template <typename Arg, typename... Args> 649b9c1b51eSKate Stone PythonObject operator()(const Arg &arg, Args... args) { 650b58fb2f4SZachary Turner return operator()({arg, args...}); 651b58fb2f4SZachary Turner } 652a1405147SZachary Turner }; 653a1405147SZachary Turner 654d3bd5b3dSLawrence D'Anna class PythonFile : public TypedPythonObject<PythonFile> { 6559c40264fSZachary Turner public: 656d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 657edb35d95SEugene Zelenko 658d3bd5b3dSLawrence D'Anna PythonFile() : TypedPythonObject() {} // MSVC requires this for some reason 6599c40264fSZachary Turner 6609c40264fSZachary Turner static bool Check(PyObject *py_obj); 6619c40264fSZachary Turner 662d9b553ecSLawrence D'Anna static llvm::Expected<PythonFile> FromFile(File &file, 663d9b553ecSLawrence D'Anna const char *mode = nullptr); 664d9b553ecSLawrence D'Anna 665085328eeSLawrence D'Anna llvm::Expected<lldb::FileSP> ConvertToFile(bool borrowed = false); 666085328eeSLawrence D'Anna llvm::Expected<lldb::FileSP> 667085328eeSLawrence D'Anna ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed = false); 6689c40264fSZachary Turner }; 6699c40264fSZachary Turner 670085328eeSLawrence D'Anna class PythonException : public llvm::ErrorInfo<PythonException> { 671085328eeSLawrence D'Anna private: 672085328eeSLawrence D'Anna PyObject *m_exception_type, *m_exception, *m_traceback; 673085328eeSLawrence D'Anna PyObject *m_repr_bytes; 674085328eeSLawrence D'Anna 675085328eeSLawrence D'Anna public: 676085328eeSLawrence D'Anna static char ID; 677085328eeSLawrence D'Anna const char *toCString() const; 678085328eeSLawrence D'Anna PythonException(const char *caller = nullptr); 679085328eeSLawrence D'Anna void Restore(); 680085328eeSLawrence D'Anna ~PythonException(); 681085328eeSLawrence D'Anna void log(llvm::raw_ostream &OS) const override; 682085328eeSLawrence D'Anna std::error_code convertToErrorCode() const override; 68304edd189SLawrence D'Anna bool Matches(PyObject *exc) const; 68404edd189SLawrence D'Anna std::string ReadBacktrace() const; 685085328eeSLawrence D'Anna }; 686085328eeSLawrence D'Anna 687085328eeSLawrence D'Anna // This extracts the underlying T out of an Expected<T> and returns it. 688085328eeSLawrence D'Anna // If the Expected is an Error instead of a T, that error will be converted 689085328eeSLawrence D'Anna // into a python exception, and this will return a default-constructed T. 690085328eeSLawrence D'Anna // 691085328eeSLawrence D'Anna // This is appropriate for use right at the boundary of python calling into 692085328eeSLawrence D'Anna // C++, such as in a SWIG typemap. In such a context you should simply 693085328eeSLawrence D'Anna // check if the returned T is valid, and if it is, return a NULL back 694085328eeSLawrence D'Anna // to python. This will result in the Error being raised as an exception 695085328eeSLawrence D'Anna // from python code's point of view. 696085328eeSLawrence D'Anna // 697085328eeSLawrence D'Anna // For example: 698085328eeSLawrence D'Anna // ``` 699085328eeSLawrence D'Anna // Expected<Foo *> efoop = some_cpp_function(); 700085328eeSLawrence D'Anna // Foo *foop = unwrapOrSetPythonException(efoop); 701085328eeSLawrence D'Anna // if (!foop) 702085328eeSLawrence D'Anna // return NULL; 703085328eeSLawrence D'Anna // do_something(*foop); 704085328eeSLawrence D'Anna // 705085328eeSLawrence D'Anna // If the Error returned was itself created because a python exception was 706085328eeSLawrence D'Anna // raised when C++ code called into python, then the original exception 707085328eeSLawrence D'Anna // will be restored. Otherwise a simple string exception will be raised. 708085328eeSLawrence D'Anna template <typename T> T unwrapOrSetPythonException(llvm::Expected<T> expected) { 709085328eeSLawrence D'Anna if (expected) 710085328eeSLawrence D'Anna return expected.get(); 711085328eeSLawrence D'Anna llvm::handleAllErrors( 712085328eeSLawrence D'Anna expected.takeError(), [](PythonException &E) { E.Restore(); }, 713085328eeSLawrence D'Anna [](const llvm::ErrorInfoBase &E) { 714085328eeSLawrence D'Anna PyErr_SetString(PyExc_Exception, E.message().c_str()); 715085328eeSLawrence D'Anna }); 716085328eeSLawrence D'Anna return T(); 717085328eeSLawrence D'Anna } 718085328eeSLawrence D'Anna 719722b6189SLawrence D'Anna // This is only here to help incrementally migrate old, exception-unsafe 720722b6189SLawrence D'Anna // code. 721722b6189SLawrence D'Anna template <typename T> T unwrapIgnoringErrors(llvm::Expected<T> expected) { 722722b6189SLawrence D'Anna if (expected) 723722b6189SLawrence D'Anna return std::move(expected.get()); 724722b6189SLawrence D'Anna llvm::consumeError(expected.takeError()); 725722b6189SLawrence D'Anna return T(); 726722b6189SLawrence D'Anna } 727722b6189SLawrence D'Anna 72804edd189SLawrence D'Anna llvm::Expected<PythonObject> runStringOneLine(const llvm::Twine &string, 72904edd189SLawrence D'Anna const PythonDictionary &globals, 73004edd189SLawrence D'Anna const PythonDictionary &locals); 73104edd189SLawrence D'Anna 73204edd189SLawrence D'Anna llvm::Expected<PythonObject> runStringMultiLine(const llvm::Twine &string, 73304edd189SLawrence D'Anna const PythonDictionary &globals, 73404edd189SLawrence D'Anna const PythonDictionary &locals); 73504edd189SLawrence D'Anna 73604edd189SLawrence D'Anna // Sometimes the best way to interact with a python interpreter is 73704edd189SLawrence D'Anna // to run some python code. You construct a PythonScript with 73804edd189SLawrence D'Anna // script string. The script assigns some function to `_function_` 73904edd189SLawrence D'Anna // and you get a C++ callable object that calls the python function. 74004edd189SLawrence D'Anna // 74104edd189SLawrence D'Anna // Example: 74204edd189SLawrence D'Anna // 74304edd189SLawrence D'Anna // const char script[] = R"( 74404edd189SLawrence D'Anna // def main(x, y): 74504edd189SLawrence D'Anna // .... 74604edd189SLawrence D'Anna // )"; 74704edd189SLawrence D'Anna // 74804edd189SLawrence D'Anna // Expected<PythonObject> cpp_foo_wrapper(PythonObject x, PythonObject y) { 74904edd189SLawrence D'Anna // // no need to synchronize access to this global, we already have the GIL 75004edd189SLawrence D'Anna // static PythonScript foo(script) 75104edd189SLawrence D'Anna // return foo(x, y); 75204edd189SLawrence D'Anna // } 75304edd189SLawrence D'Anna class PythonScript { 75404edd189SLawrence D'Anna const char *script; 75504edd189SLawrence D'Anna PythonCallable function; 75604edd189SLawrence D'Anna 75704edd189SLawrence D'Anna llvm::Error Init(); 75804edd189SLawrence D'Anna 75904edd189SLawrence D'Anna public: 76004edd189SLawrence D'Anna PythonScript(const char *script) : script(script), function() {} 76104edd189SLawrence D'Anna 76204edd189SLawrence D'Anna template <typename... Args> 76304edd189SLawrence D'Anna llvm::Expected<PythonObject> operator()(Args &&... args) { 76404edd189SLawrence D'Anna if (llvm::Error error = Init()) 76504edd189SLawrence D'Anna return std::move(error); 76604edd189SLawrence D'Anna return function.Call(std::forward<Args>(args)...); 76704edd189SLawrence D'Anna } 76804edd189SLawrence D'Anna }; 76904edd189SLawrence D'Anna 77004edd189SLawrence D'Anna } // namespace python 7712c1f46dcSZachary Turner } // namespace lldb_private 7722c1f46dcSZachary Turner 773a281b42bSZachary Turner #endif 774d68983e3SPavel Labath 775d68983e3SPavel Labath #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H 776