xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- PythonDataObjects.h--------------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
99dba64beSDimitry Andric //
109dba64beSDimitry Andric // !! FIXME FIXME FIXME !!
119dba64beSDimitry Andric //
129dba64beSDimitry Andric // Python APIs nearly all can return an exception.   They do this
139dba64beSDimitry Andric // by returning NULL, or -1, or some such value and setting
149dba64beSDimitry Andric // the exception state with PyErr_Set*().   Exceptions must be
159dba64beSDimitry Andric // handled before further python API functions are called.   Failure
169dba64beSDimitry Andric // to do so will result in asserts on debug builds of python.
179dba64beSDimitry Andric // It will also sometimes, but not usually result in crashes of
189dba64beSDimitry Andric // release builds.
199dba64beSDimitry Andric //
209dba64beSDimitry Andric // Nearly all the code in this header does not handle python exceptions
219dba64beSDimitry Andric // correctly.  It should all be converted to return Expected<> or
229dba64beSDimitry Andric // Error types to capture the exception.
239dba64beSDimitry Andric //
249dba64beSDimitry Andric // Everything in this file except functions that return Error or
259dba64beSDimitry Andric // Expected<> is considered deprecated and should not be
269dba64beSDimitry Andric // used in new code.  If you need to use it, fix it first.
279dba64beSDimitry Andric //
289dba64beSDimitry Andric //
299dba64beSDimitry Andric // TODOs for this file
309dba64beSDimitry Andric //
319dba64beSDimitry Andric // * Make all methods safe for exceptions.
329dba64beSDimitry Andric //
339dba64beSDimitry Andric // * Eliminate method signatures that must translate exceptions into
349dba64beSDimitry Andric //   empty objects or NULLs.   Almost everything here should return
359dba64beSDimitry Andric //   Expected<>.   It should be acceptable for certain operations that
369dba64beSDimitry Andric //   can never fail to assert instead, such as the creation of
379dba64beSDimitry Andric //   PythonString from a string literal.
389dba64beSDimitry Andric //
395ffd83dbSDimitry Andric // * Eliminate Reset(), and make all non-default constructors private.
409dba64beSDimitry Andric //   Python objects should be created with Retain<> or Take<>, and they
419dba64beSDimitry Andric //   should be assigned with operator=
429dba64beSDimitry Andric //
439dba64beSDimitry Andric // * Eliminate default constructors, make python objects always
449dba64beSDimitry Andric //   nonnull, and use optionals where necessary.
459dba64beSDimitry Andric //
469dba64beSDimitry Andric 
479dba64beSDimitry Andric 
480b57cec5SDimitry Andric #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
490b57cec5SDimitry Andric #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
500b57cec5SDimitry Andric 
51480093f4SDimitry Andric #include "lldb/Host/Config.h"
52480093f4SDimitry Andric 
53480093f4SDimitry Andric #if LLDB_ENABLE_PYTHON
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric // LLDB Python header must be included first
560b57cec5SDimitry Andric #include "lldb-python.h"
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric #include "lldb/Host/File.h"
590b57cec5SDimitry Andric #include "lldb/Utility/StructuredData.h"
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric namespace lldb_private {
649dba64beSDimitry Andric namespace python {
650b57cec5SDimitry Andric 
669dba64beSDimitry Andric class PythonObject;
670b57cec5SDimitry Andric class PythonBytes;
680b57cec5SDimitry Andric class PythonString;
690b57cec5SDimitry Andric class PythonList;
700b57cec5SDimitry Andric class PythonDictionary;
710b57cec5SDimitry Andric class PythonInteger;
729dba64beSDimitry Andric class PythonException;
730b57cec5SDimitry Andric 
74349cc55cSDimitry Andric class GIL {
75349cc55cSDimitry Andric public:
76349cc55cSDimitry Andric   GIL() {
77349cc55cSDimitry Andric     m_state = PyGILState_Ensure();
78349cc55cSDimitry Andric     assert(!PyErr_Occurred());
79349cc55cSDimitry Andric   }
80349cc55cSDimitry Andric   ~GIL() { PyGILState_Release(m_state); }
81349cc55cSDimitry Andric 
82349cc55cSDimitry Andric protected:
83349cc55cSDimitry Andric   PyGILState_STATE m_state;
84349cc55cSDimitry Andric };
85349cc55cSDimitry Andric 
860b57cec5SDimitry Andric enum class PyObjectType {
870b57cec5SDimitry Andric   Unknown,
880b57cec5SDimitry Andric   None,
890b57cec5SDimitry Andric   Boolean,
900b57cec5SDimitry Andric   Integer,
910b57cec5SDimitry Andric   Dictionary,
920b57cec5SDimitry Andric   List,
930b57cec5SDimitry Andric   String,
940b57cec5SDimitry Andric   Bytes,
950b57cec5SDimitry Andric   ByteArray,
960b57cec5SDimitry Andric   Module,
970b57cec5SDimitry Andric   Callable,
980b57cec5SDimitry Andric   Tuple,
990b57cec5SDimitry Andric   File
1000b57cec5SDimitry Andric };
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric enum class PyRefType {
1030b57cec5SDimitry Andric   Borrowed, // We are not given ownership of the incoming PyObject.
1040b57cec5SDimitry Andric             // We cannot safely hold it without calling Py_INCREF.
1050b57cec5SDimitry Andric   Owned     // We have ownership of the incoming PyObject.  We should
1060b57cec5SDimitry Andric             // not call Py_INCREF.
1070b57cec5SDimitry Andric };
1080b57cec5SDimitry Andric 
1099dba64beSDimitry Andric 
1109dba64beSDimitry Andric // Take a reference that you already own, and turn it into
1119dba64beSDimitry Andric // a PythonObject.
1129dba64beSDimitry Andric //
1139dba64beSDimitry Andric // Most python API methods will return a +1 reference
1149dba64beSDimitry Andric // if they succeed or NULL if and only if
1159dba64beSDimitry Andric // they set an exception.   Use this to collect such return
1169dba64beSDimitry Andric // values, after checking for NULL.
1179dba64beSDimitry Andric //
1189dba64beSDimitry Andric // If T is not just PythonObject, then obj must be already be
1199dba64beSDimitry Andric // checked to be of the correct type.
1209dba64beSDimitry Andric template <typename T> T Take(PyObject *obj) {
1219dba64beSDimitry Andric   assert(obj);
1229dba64beSDimitry Andric   assert(!PyErr_Occurred());
1239dba64beSDimitry Andric   T thing(PyRefType::Owned, obj);
1249dba64beSDimitry Andric   assert(thing.IsValid());
125480093f4SDimitry Andric   return thing;
1269dba64beSDimitry Andric }
1279dba64beSDimitry Andric 
1289dba64beSDimitry Andric // Retain a reference you have borrowed, and turn it into
1299dba64beSDimitry Andric // a PythonObject.
1309dba64beSDimitry Andric //
1319dba64beSDimitry Andric // A minority of python APIs return a borrowed reference
1329dba64beSDimitry Andric // instead of a +1.   They will also return NULL if and only
1339dba64beSDimitry Andric // if they set an exception.   Use this to collect such return
1349dba64beSDimitry Andric // values, after checking for NULL.
1359dba64beSDimitry Andric //
1369dba64beSDimitry Andric // If T is not just PythonObject, then obj must be already be
1379dba64beSDimitry Andric // checked to be of the correct type.
1389dba64beSDimitry Andric template <typename T> T Retain(PyObject *obj) {
1399dba64beSDimitry Andric   assert(obj);
1409dba64beSDimitry Andric   assert(!PyErr_Occurred());
1419dba64beSDimitry Andric   T thing(PyRefType::Borrowed, obj);
1429dba64beSDimitry Andric   assert(thing.IsValid());
143480093f4SDimitry Andric   return thing;
1449dba64beSDimitry Andric }
1459dba64beSDimitry Andric 
1469dba64beSDimitry Andric // This class can be used like a utility function to convert from
1479dba64beSDimitry Andric // a llvm-friendly Twine into a null-terminated const char *,
1489dba64beSDimitry Andric // which is the form python C APIs want their strings in.
1499dba64beSDimitry Andric //
1509dba64beSDimitry Andric // Example:
1519dba64beSDimitry Andric // const llvm::Twine &some_twine;
1529dba64beSDimitry Andric // PyFoo_Bar(x, y, z, NullTerminated(some_twine));
1539dba64beSDimitry Andric //
1549dba64beSDimitry Andric // Why a class instead of a function?  If the twine isn't already null
1559dba64beSDimitry Andric // terminated, it will need a temporary buffer to copy the string
1569dba64beSDimitry Andric // into.   We need that buffer to stick around for the lifetime of the
1579dba64beSDimitry Andric // statement.
1589dba64beSDimitry Andric class NullTerminated {
1599dba64beSDimitry Andric   const char *str;
1609dba64beSDimitry Andric   llvm::SmallString<32> storage;
1619dba64beSDimitry Andric 
1629dba64beSDimitry Andric public:
1639dba64beSDimitry Andric   NullTerminated(const llvm::Twine &twine) {
1649dba64beSDimitry Andric     llvm::StringRef ref = twine.toNullTerminatedStringRef(storage);
1659dba64beSDimitry Andric     str = ref.begin();
1669dba64beSDimitry Andric   }
1679dba64beSDimitry Andric   operator const char *() { return str; }
1689dba64beSDimitry Andric };
1699dba64beSDimitry Andric 
1709dba64beSDimitry Andric inline llvm::Error nullDeref() {
1719dba64beSDimitry Andric   return llvm::createStringError(llvm::inconvertibleErrorCode(),
1729dba64beSDimitry Andric                                  "A NULL PyObject* was dereferenced");
1739dba64beSDimitry Andric }
1749dba64beSDimitry Andric 
1759dba64beSDimitry Andric inline llvm::Error exception(const char *s = nullptr) {
1769dba64beSDimitry Andric   return llvm::make_error<PythonException>(s);
1779dba64beSDimitry Andric }
1789dba64beSDimitry Andric 
1799dba64beSDimitry Andric inline llvm::Error keyError() {
1809dba64beSDimitry Andric   return llvm::createStringError(llvm::inconvertibleErrorCode(),
1819dba64beSDimitry Andric                                  "key not in dict");
1829dba64beSDimitry Andric }
1839dba64beSDimitry Andric 
184480093f4SDimitry Andric inline const char *py2_const_cast(const char *s) { return s; }
185480093f4SDimitry Andric 
1860b57cec5SDimitry Andric enum class PyInitialValue { Invalid, Empty };
1870b57cec5SDimitry Andric 
188bdd1243dSDimitry Andric // DOC: https://docs.python.org/3/c-api/arg.html#building-values
1899dba64beSDimitry Andric template <typename T, typename Enable = void> struct PythonFormat;
1909dba64beSDimitry Andric 
191bdd1243dSDimitry Andric template <typename T, char F> struct PassthroughFormat {
192bdd1243dSDimitry Andric   static constexpr char format = F;
193bdd1243dSDimitry Andric   static constexpr T get(T t) { return t; }
1949dba64beSDimitry Andric };
1959dba64beSDimitry Andric 
196bdd1243dSDimitry Andric template <> struct PythonFormat<char *> : PassthroughFormat<char *, 's'> {};
197*0fca6ea1SDimitry Andric template <> struct PythonFormat<const char *> :
198*0fca6ea1SDimitry Andric     PassthroughFormat<const char *, 's'> {};
199bdd1243dSDimitry Andric template <> struct PythonFormat<char> : PassthroughFormat<char, 'b'> {};
200bdd1243dSDimitry Andric template <>
201bdd1243dSDimitry Andric struct PythonFormat<unsigned char> : PassthroughFormat<unsigned char, 'B'> {};
202bdd1243dSDimitry Andric template <> struct PythonFormat<short> : PassthroughFormat<short, 'h'> {};
203bdd1243dSDimitry Andric template <>
204bdd1243dSDimitry Andric struct PythonFormat<unsigned short> : PassthroughFormat<unsigned short, 'H'> {};
205bdd1243dSDimitry Andric template <> struct PythonFormat<int> : PassthroughFormat<int, 'i'> {};
20606c3fb27SDimitry Andric template <> struct PythonFormat<bool> : PassthroughFormat<bool, 'p'> {};
207bdd1243dSDimitry Andric template <>
208bdd1243dSDimitry Andric struct PythonFormat<unsigned int> : PassthroughFormat<unsigned int, 'I'> {};
209bdd1243dSDimitry Andric template <> struct PythonFormat<long> : PassthroughFormat<long, 'l'> {};
210bdd1243dSDimitry Andric template <>
211bdd1243dSDimitry Andric struct PythonFormat<unsigned long> : PassthroughFormat<unsigned long, 'k'> {};
212bdd1243dSDimitry Andric template <>
213bdd1243dSDimitry Andric struct PythonFormat<long long> : PassthroughFormat<long long, 'L'> {};
214bdd1243dSDimitry Andric template <>
215bdd1243dSDimitry Andric struct PythonFormat<unsigned long long>
216bdd1243dSDimitry Andric     : PassthroughFormat<unsigned long long, 'K'> {};
217bdd1243dSDimitry Andric template <>
218bdd1243dSDimitry Andric struct PythonFormat<PyObject *> : PassthroughFormat<PyObject *, 'O'> {};
2199dba64beSDimitry Andric 
2209dba64beSDimitry Andric template <typename T>
2219dba64beSDimitry Andric struct PythonFormat<
2229dba64beSDimitry Andric     T, typename std::enable_if<std::is_base_of<PythonObject, T>::value>::type> {
2239dba64beSDimitry Andric   static constexpr char format = 'O';
2249dba64beSDimitry Andric   static auto get(const T &value) { return value.get(); }
2259dba64beSDimitry Andric };
2269dba64beSDimitry Andric 
2270b57cec5SDimitry Andric class PythonObject {
2280b57cec5SDimitry Andric public:
229fe6060f1SDimitry Andric   PythonObject() = default;
2300b57cec5SDimitry Andric 
2319dba64beSDimitry Andric   PythonObject(PyRefType type, PyObject *py_obj) {
2320b57cec5SDimitry Andric     m_py_obj = py_obj;
2330b57cec5SDimitry Andric     // If this is a borrowed reference, we need to convert it to
2340b57cec5SDimitry Andric     // an owned reference by incrementing it.  If it is an owned
2350b57cec5SDimitry Andric     // reference (for example the caller allocated it with PyDict_New()
2360b57cec5SDimitry Andric     // then we must *not* increment it.
2379dba64beSDimitry Andric     if (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed)
2380b57cec5SDimitry Andric       Py_XINCREF(m_py_obj);
2390b57cec5SDimitry Andric   }
2400b57cec5SDimitry Andric 
2419dba64beSDimitry Andric   PythonObject(const PythonObject &rhs)
2429dba64beSDimitry Andric       : PythonObject(PyRefType::Borrowed, rhs.m_py_obj) {}
2439dba64beSDimitry Andric 
2449dba64beSDimitry Andric   PythonObject(PythonObject &&rhs) {
2459dba64beSDimitry Andric     m_py_obj = rhs.m_py_obj;
2469dba64beSDimitry Andric     rhs.m_py_obj = nullptr;
2479dba64beSDimitry Andric   }
2489dba64beSDimitry Andric 
2499dba64beSDimitry Andric   ~PythonObject() { Reset(); }
2509dba64beSDimitry Andric 
25104eeddc0SDimitry Andric   void Reset();
2529dba64beSDimitry Andric 
2530b57cec5SDimitry Andric   void Dump() const {
2540b57cec5SDimitry Andric     if (m_py_obj)
2550b57cec5SDimitry Andric       _PyObject_Dump(m_py_obj);
2560b57cec5SDimitry Andric     else
2570b57cec5SDimitry Andric       puts("NULL");
2580b57cec5SDimitry Andric   }
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric   void Dump(Stream &strm) const;
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric   PyObject *get() const { return m_py_obj; }
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric   PyObject *release() {
2650b57cec5SDimitry Andric     PyObject *result = m_py_obj;
2660b57cec5SDimitry Andric     m_py_obj = nullptr;
2670b57cec5SDimitry Andric     return result;
2680b57cec5SDimitry Andric   }
2690b57cec5SDimitry Andric 
2709dba64beSDimitry Andric   PythonObject &operator=(PythonObject other) {
2719dba64beSDimitry Andric     Reset();
2729dba64beSDimitry Andric     m_py_obj = std::exchange(other.m_py_obj, nullptr);
2730b57cec5SDimitry Andric     return *this;
2740b57cec5SDimitry Andric   }
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric   PyObjectType GetObjectType() const;
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric   PythonString Repr() const;
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric   PythonString Str() const;
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric   static PythonObject ResolveNameWithDictionary(llvm::StringRef name,
2830b57cec5SDimitry Andric                                                 const PythonDictionary &dict);
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric   template <typename T>
2860b57cec5SDimitry Andric   static T ResolveNameWithDictionary(llvm::StringRef name,
2870b57cec5SDimitry Andric                                      const PythonDictionary &dict) {
2880b57cec5SDimitry Andric     return ResolveNameWithDictionary(name, dict).AsType<T>();
2890b57cec5SDimitry Andric   }
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric   PythonObject ResolveName(llvm::StringRef name) const;
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric   template <typename T> T ResolveName(llvm::StringRef name) const {
2940b57cec5SDimitry Andric     return ResolveName(name).AsType<T>();
2950b57cec5SDimitry Andric   }
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric   bool HasAttribute(llvm::StringRef attribute) const;
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   PythonObject GetAttributeValue(llvm::StringRef attribute) const;
3000b57cec5SDimitry Andric 
3019dba64beSDimitry Andric   bool IsNone() const { return m_py_obj == Py_None; }
3020b57cec5SDimitry Andric 
3039dba64beSDimitry Andric   bool IsValid() const { return m_py_obj != nullptr; }
3040b57cec5SDimitry Andric 
3059dba64beSDimitry Andric   bool IsAllocated() const { return IsValid() && !IsNone(); }
3069dba64beSDimitry Andric 
3079dba64beSDimitry Andric   explicit operator bool() const { return IsValid() && !IsNone(); }
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   template <typename T> T AsType() const {
3100b57cec5SDimitry Andric     if (!T::Check(m_py_obj))
3110b57cec5SDimitry Andric       return T();
3120b57cec5SDimitry Andric     return T(PyRefType::Borrowed, m_py_obj);
3130b57cec5SDimitry Andric   }
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric   StructuredData::ObjectSP CreateStructuredObject() const;
3160b57cec5SDimitry Andric 
3179dba64beSDimitry Andric   template <typename... T>
3189dba64beSDimitry Andric   llvm::Expected<PythonObject> CallMethod(const char *name,
3199dba64beSDimitry Andric                                           const T &... t) const {
3209dba64beSDimitry Andric     const char format[] = {'(', PythonFormat<T>::format..., ')', 0};
3219dba64beSDimitry Andric     PyObject *obj =
3229dba64beSDimitry Andric         PyObject_CallMethod(m_py_obj, py2_const_cast(name),
3239dba64beSDimitry Andric                             py2_const_cast(format), PythonFormat<T>::get(t)...);
3249dba64beSDimitry Andric     if (!obj)
3259dba64beSDimitry Andric       return exception();
3269dba64beSDimitry Andric     return python::Take<PythonObject>(obj);
3279dba64beSDimitry Andric   }
3289dba64beSDimitry Andric 
3299dba64beSDimitry Andric   template <typename... T>
3309dba64beSDimitry Andric   llvm::Expected<PythonObject> Call(const T &... t) const {
3319dba64beSDimitry Andric     const char format[] = {'(', PythonFormat<T>::format..., ')', 0};
3329dba64beSDimitry Andric     PyObject *obj = PyObject_CallFunction(m_py_obj, py2_const_cast(format),
3339dba64beSDimitry Andric                                           PythonFormat<T>::get(t)...);
3349dba64beSDimitry Andric     if (!obj)
3359dba64beSDimitry Andric       return exception();
3369dba64beSDimitry Andric     return python::Take<PythonObject>(obj);
3379dba64beSDimitry Andric   }
3389dba64beSDimitry Andric 
3399dba64beSDimitry Andric   llvm::Expected<PythonObject> GetAttribute(const llvm::Twine &name) const {
3409dba64beSDimitry Andric     if (!m_py_obj)
3419dba64beSDimitry Andric       return nullDeref();
3429dba64beSDimitry Andric     PyObject *obj = PyObject_GetAttrString(m_py_obj, NullTerminated(name));
3439dba64beSDimitry Andric     if (!obj)
3449dba64beSDimitry Andric       return exception();
3459dba64beSDimitry Andric     return python::Take<PythonObject>(obj);
3469dba64beSDimitry Andric   }
3479dba64beSDimitry Andric 
34806c3fb27SDimitry Andric   llvm::Expected<PythonObject> GetType() const {
34906c3fb27SDimitry Andric     if (!m_py_obj)
35006c3fb27SDimitry Andric       return nullDeref();
35106c3fb27SDimitry Andric     PyObject *obj = PyObject_Type(m_py_obj);
35206c3fb27SDimitry Andric     if (!obj)
35306c3fb27SDimitry Andric       return exception();
35406c3fb27SDimitry Andric     return python::Take<PythonObject>(obj);
35506c3fb27SDimitry Andric   }
35606c3fb27SDimitry Andric 
3579dba64beSDimitry Andric   llvm::Expected<bool> IsTrue() {
3589dba64beSDimitry Andric     if (!m_py_obj)
3599dba64beSDimitry Andric       return nullDeref();
3609dba64beSDimitry Andric     int r = PyObject_IsTrue(m_py_obj);
3619dba64beSDimitry Andric     if (r < 0)
3629dba64beSDimitry Andric       return exception();
3639dba64beSDimitry Andric     return !!r;
3649dba64beSDimitry Andric   }
3659dba64beSDimitry Andric 
3665ffd83dbSDimitry Andric   llvm::Expected<long long> AsLongLong() const;
3675ffd83dbSDimitry Andric 
36806c3fb27SDimitry Andric   llvm::Expected<unsigned long long> AsUnsignedLongLong() const;
3695ffd83dbSDimitry Andric 
3705ffd83dbSDimitry Andric   // wraps on overflow, instead of raising an error.
3715ffd83dbSDimitry Andric   llvm::Expected<unsigned long long> AsModuloUnsignedLongLong() const;
3729dba64beSDimitry Andric 
3739dba64beSDimitry Andric   llvm::Expected<bool> IsInstance(const PythonObject &cls) {
3749dba64beSDimitry Andric     if (!m_py_obj || !cls.IsValid())
3759dba64beSDimitry Andric       return nullDeref();
3769dba64beSDimitry Andric     int r = PyObject_IsInstance(m_py_obj, cls.get());
3779dba64beSDimitry Andric     if (r < 0)
3789dba64beSDimitry Andric       return exception();
3799dba64beSDimitry Andric     return !!r;
3809dba64beSDimitry Andric   }
3819dba64beSDimitry Andric 
3829dba64beSDimitry Andric protected:
383fe6060f1SDimitry Andric   PyObject *m_py_obj = nullptr;
3840b57cec5SDimitry Andric };
3850b57cec5SDimitry Andric 
3869dba64beSDimitry Andric 
3879dba64beSDimitry Andric // This is why C++ needs monads.
3889dba64beSDimitry Andric template <typename T> llvm::Expected<T> As(llvm::Expected<PythonObject> &&obj) {
3899dba64beSDimitry Andric   if (!obj)
3909dba64beSDimitry Andric     return obj.takeError();
3919dba64beSDimitry Andric   if (!T::Check(obj.get().get()))
3929dba64beSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
3939dba64beSDimitry Andric                                    "type error");
3949dba64beSDimitry Andric   return T(PyRefType::Borrowed, std::move(obj.get().get()));
3959dba64beSDimitry Andric }
3969dba64beSDimitry Andric 
3979dba64beSDimitry Andric template <> llvm::Expected<bool> As<bool>(llvm::Expected<PythonObject> &&obj);
3989dba64beSDimitry Andric 
3999dba64beSDimitry Andric template <>
4009dba64beSDimitry Andric llvm::Expected<long long> As<long long>(llvm::Expected<PythonObject> &&obj);
4019dba64beSDimitry Andric 
4029dba64beSDimitry Andric template <>
4035ffd83dbSDimitry Andric llvm::Expected<unsigned long long>
4045ffd83dbSDimitry Andric As<unsigned long long>(llvm::Expected<PythonObject> &&obj);
4055ffd83dbSDimitry Andric 
4065ffd83dbSDimitry Andric template <>
4079dba64beSDimitry Andric llvm::Expected<std::string> As<std::string>(llvm::Expected<PythonObject> &&obj);
4089dba64beSDimitry Andric 
4099dba64beSDimitry Andric 
4109dba64beSDimitry Andric template <class T> class TypedPythonObject : public PythonObject {
4110b57cec5SDimitry Andric public:
4129dba64beSDimitry Andric   TypedPythonObject(PyRefType type, PyObject *py_obj) {
4139dba64beSDimitry Andric     if (!py_obj)
4149dba64beSDimitry Andric       return;
4159dba64beSDimitry Andric     if (T::Check(py_obj))
4169dba64beSDimitry Andric       PythonObject::operator=(PythonObject(type, py_obj));
4179dba64beSDimitry Andric     else if (type == PyRefType::Owned)
4189dba64beSDimitry Andric       Py_DECREF(py_obj);
4199dba64beSDimitry Andric   }
4209dba64beSDimitry Andric 
421fe6060f1SDimitry Andric   TypedPythonObject() = default;
4229dba64beSDimitry Andric };
4239dba64beSDimitry Andric 
4249dba64beSDimitry Andric class PythonBytes : public TypedPythonObject<PythonBytes> {
4259dba64beSDimitry Andric public:
4269dba64beSDimitry Andric   using TypedPythonObject::TypedPythonObject;
4270b57cec5SDimitry Andric   explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes);
4280b57cec5SDimitry Andric   PythonBytes(const uint8_t *bytes, size_t length);
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric   static bool Check(PyObject *py_obj);
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric   llvm::ArrayRef<uint8_t> GetBytes() const;
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric   size_t GetSize() const;
4350b57cec5SDimitry Andric 
4360b57cec5SDimitry Andric   void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric   StructuredData::StringSP CreateStructuredString() const;
4390b57cec5SDimitry Andric };
4400b57cec5SDimitry Andric 
4419dba64beSDimitry Andric class PythonByteArray : public TypedPythonObject<PythonByteArray> {
4420b57cec5SDimitry Andric public:
4439dba64beSDimitry Andric   using TypedPythonObject::TypedPythonObject;
4440b57cec5SDimitry Andric   explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes);
4450b57cec5SDimitry Andric   PythonByteArray(const uint8_t *bytes, size_t length);
4460b57cec5SDimitry Andric   PythonByteArray(const PythonBytes &object);
4470b57cec5SDimitry Andric 
4480b57cec5SDimitry Andric   static bool Check(PyObject *py_obj);
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric   llvm::ArrayRef<uint8_t> GetBytes() const;
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric   size_t GetSize() const;
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric   void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
4550b57cec5SDimitry Andric 
4560b57cec5SDimitry Andric   StructuredData::StringSP CreateStructuredString() const;
4570b57cec5SDimitry Andric };
4580b57cec5SDimitry Andric 
4599dba64beSDimitry Andric class PythonString : public TypedPythonObject<PythonString> {
4600b57cec5SDimitry Andric public:
4619dba64beSDimitry Andric   using TypedPythonObject::TypedPythonObject;
4629dba64beSDimitry Andric   static llvm::Expected<PythonString> FromUTF8(llvm::StringRef string);
4630b57cec5SDimitry Andric 
4649dba64beSDimitry Andric   PythonString() : TypedPythonObject() {} // MSVC requires this for some reason
4659dba64beSDimitry Andric 
4669dba64beSDimitry Andric   explicit PythonString(llvm::StringRef string); // safe, null on error
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric   static bool Check(PyObject *py_obj);
4690b57cec5SDimitry Andric 
4709dba64beSDimitry Andric   llvm::StringRef GetString() const; // safe, empty string on error
4710b57cec5SDimitry Andric 
4729dba64beSDimitry Andric   llvm::Expected<llvm::StringRef> AsUTF8() const;
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric   size_t GetSize() const;
4750b57cec5SDimitry Andric 
4769dba64beSDimitry Andric   void SetString(llvm::StringRef string); // safe, null on error
4770b57cec5SDimitry Andric 
4780b57cec5SDimitry Andric   StructuredData::StringSP CreateStructuredString() const;
4790b57cec5SDimitry Andric };
4800b57cec5SDimitry Andric 
4819dba64beSDimitry Andric class PythonInteger : public TypedPythonObject<PythonInteger> {
4820b57cec5SDimitry Andric public:
4839dba64beSDimitry Andric   using TypedPythonObject::TypedPythonObject;
4840b57cec5SDimitry Andric 
4859dba64beSDimitry Andric   PythonInteger() : TypedPythonObject() {} // MSVC requires this for some reason
4869dba64beSDimitry Andric 
4879dba64beSDimitry Andric   explicit PythonInteger(int64_t value);
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric   static bool Check(PyObject *py_obj);
4900b57cec5SDimitry Andric 
4910b57cec5SDimitry Andric   void SetInteger(int64_t value);
4920b57cec5SDimitry Andric 
4930b57cec5SDimitry Andric   StructuredData::IntegerSP CreateStructuredInteger() const;
49406c3fb27SDimitry Andric 
49506c3fb27SDimitry Andric   StructuredData::UnsignedIntegerSP CreateStructuredUnsignedInteger() const;
49606c3fb27SDimitry Andric 
49706c3fb27SDimitry Andric   StructuredData::SignedIntegerSP CreateStructuredSignedInteger() const;
4980b57cec5SDimitry Andric };
4990b57cec5SDimitry Andric 
5009dba64beSDimitry Andric class PythonBoolean : public TypedPythonObject<PythonBoolean> {
5010b57cec5SDimitry Andric public:
5029dba64beSDimitry Andric   using TypedPythonObject::TypedPythonObject;
5030b57cec5SDimitry Andric 
5049dba64beSDimitry Andric   explicit PythonBoolean(bool value);
5050b57cec5SDimitry Andric 
5060b57cec5SDimitry Andric   static bool Check(PyObject *py_obj);
5070b57cec5SDimitry Andric 
5080b57cec5SDimitry Andric   bool GetValue() const;
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric   void SetValue(bool value);
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric   StructuredData::BooleanSP CreateStructuredBoolean() const;
5130b57cec5SDimitry Andric };
5140b57cec5SDimitry Andric 
5159dba64beSDimitry Andric class PythonList : public TypedPythonObject<PythonList> {
5160b57cec5SDimitry Andric public:
5179dba64beSDimitry Andric   using TypedPythonObject::TypedPythonObject;
5189dba64beSDimitry Andric 
5199dba64beSDimitry Andric   PythonList() : TypedPythonObject() {} // MSVC requires this for some reason
5209dba64beSDimitry Andric 
5210b57cec5SDimitry Andric   explicit PythonList(PyInitialValue value);
5220b57cec5SDimitry Andric   explicit PythonList(int list_size);
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric   static bool Check(PyObject *py_obj);
5250b57cec5SDimitry Andric 
5260b57cec5SDimitry Andric   uint32_t GetSize() const;
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric   PythonObject GetItemAtIndex(uint32_t index) const;
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric   void SetItemAtIndex(uint32_t index, const PythonObject &object);
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric   void AppendItem(const PythonObject &object);
5330b57cec5SDimitry Andric 
5340b57cec5SDimitry Andric   StructuredData::ArraySP CreateStructuredArray() const;
5350b57cec5SDimitry Andric };
5360b57cec5SDimitry Andric 
5379dba64beSDimitry Andric class PythonTuple : public TypedPythonObject<PythonTuple> {
5380b57cec5SDimitry Andric public:
5399dba64beSDimitry Andric   using TypedPythonObject::TypedPythonObject;
5409dba64beSDimitry Andric 
5410b57cec5SDimitry Andric   explicit PythonTuple(PyInitialValue value);
5420b57cec5SDimitry Andric   explicit PythonTuple(int tuple_size);
5430b57cec5SDimitry Andric   PythonTuple(std::initializer_list<PythonObject> objects);
5440b57cec5SDimitry Andric   PythonTuple(std::initializer_list<PyObject *> objects);
5450b57cec5SDimitry Andric 
5460b57cec5SDimitry Andric   static bool Check(PyObject *py_obj);
5470b57cec5SDimitry Andric 
5480b57cec5SDimitry Andric   uint32_t GetSize() const;
5490b57cec5SDimitry Andric 
5500b57cec5SDimitry Andric   PythonObject GetItemAtIndex(uint32_t index) const;
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric   void SetItemAtIndex(uint32_t index, const PythonObject &object);
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric   StructuredData::ArraySP CreateStructuredArray() const;
5550b57cec5SDimitry Andric };
5560b57cec5SDimitry Andric 
5579dba64beSDimitry Andric class PythonDictionary : public TypedPythonObject<PythonDictionary> {
5580b57cec5SDimitry Andric public:
5599dba64beSDimitry Andric   using TypedPythonObject::TypedPythonObject;
5600b57cec5SDimitry Andric 
5619dba64beSDimitry Andric   PythonDictionary() : TypedPythonObject() {} // MSVC requires this for some reason
5629dba64beSDimitry Andric 
5639dba64beSDimitry Andric   explicit PythonDictionary(PyInitialValue value);
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric   static bool Check(PyObject *py_obj);
5660b57cec5SDimitry Andric 
5675f757f3fSDimitry Andric   bool HasKey(const llvm::Twine &key) const;
5685f757f3fSDimitry Andric 
5690b57cec5SDimitry Andric   uint32_t GetSize() const;
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric   PythonList GetKeys() const;
5720b57cec5SDimitry Andric 
5739dba64beSDimitry Andric   PythonObject GetItemForKey(const PythonObject &key) const; // DEPRECATED
5749dba64beSDimitry Andric   void SetItemForKey(const PythonObject &key,
5759dba64beSDimitry Andric                      const PythonObject &value); // DEPRECATED
5769dba64beSDimitry Andric 
5779dba64beSDimitry Andric   llvm::Expected<PythonObject> GetItem(const PythonObject &key) const;
5789dba64beSDimitry Andric   llvm::Expected<PythonObject> GetItem(const llvm::Twine &key) const;
5799dba64beSDimitry Andric   llvm::Error SetItem(const PythonObject &key, const PythonObject &value) const;
5809dba64beSDimitry Andric   llvm::Error SetItem(const llvm::Twine &key, const PythonObject &value) const;
5810b57cec5SDimitry Andric 
5820b57cec5SDimitry Andric   StructuredData::DictionarySP CreateStructuredDictionary() const;
5830b57cec5SDimitry Andric };
5840b57cec5SDimitry Andric 
5859dba64beSDimitry Andric class PythonModule : public TypedPythonObject<PythonModule> {
5860b57cec5SDimitry Andric public:
5879dba64beSDimitry Andric   using TypedPythonObject::TypedPythonObject;
5880b57cec5SDimitry Andric 
5890b57cec5SDimitry Andric   static bool Check(PyObject *py_obj);
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric   static PythonModule BuiltinsModule();
5920b57cec5SDimitry Andric 
5930b57cec5SDimitry Andric   static PythonModule MainModule();
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric   static PythonModule AddModule(llvm::StringRef module);
5960b57cec5SDimitry Andric 
5979dba64beSDimitry Andric   // safe, returns invalid on error;
5989dba64beSDimitry Andric   static PythonModule ImportModule(llvm::StringRef name) {
5995ffd83dbSDimitry Andric     std::string s = std::string(name);
6009dba64beSDimitry Andric     auto mod = Import(s.c_str());
6019dba64beSDimitry Andric     if (!mod) {
6029dba64beSDimitry Andric       llvm::consumeError(mod.takeError());
6039dba64beSDimitry Andric       return PythonModule();
6049dba64beSDimitry Andric     }
6059dba64beSDimitry Andric     return std::move(mod.get());
6069dba64beSDimitry Andric   }
6070b57cec5SDimitry Andric 
6089dba64beSDimitry Andric   static llvm::Expected<PythonModule> Import(const llvm::Twine &name);
6090b57cec5SDimitry Andric 
6109dba64beSDimitry Andric   llvm::Expected<PythonObject> Get(const llvm::Twine &name);
6110b57cec5SDimitry Andric 
6120b57cec5SDimitry Andric   PythonDictionary GetDictionary() const;
6130b57cec5SDimitry Andric };
6140b57cec5SDimitry Andric 
6159dba64beSDimitry Andric class PythonCallable : public TypedPythonObject<PythonCallable> {
6160b57cec5SDimitry Andric public:
6179dba64beSDimitry Andric   using TypedPythonObject::TypedPythonObject;
6189dba64beSDimitry Andric 
6190b57cec5SDimitry Andric   struct ArgInfo {
6209dba64beSDimitry Andric     /* the largest number of positional arguments this callable
6219dba64beSDimitry Andric      * can accept, or UNBOUNDED, ie UINT_MAX if it's a varargs
6229dba64beSDimitry Andric      * function and can accept an arbitrary number */
6239dba64beSDimitry Andric     unsigned max_positional_args;
6249dba64beSDimitry Andric     static constexpr unsigned UNBOUNDED = UINT_MAX; // FIXME c++17 inline
6250b57cec5SDimitry Andric   };
6260b57cec5SDimitry Andric 
6270b57cec5SDimitry Andric   static bool Check(PyObject *py_obj);
6280b57cec5SDimitry Andric 
6299dba64beSDimitry Andric   llvm::Expected<ArgInfo> GetArgInfo() const;
6300b57cec5SDimitry Andric 
6310b57cec5SDimitry Andric   PythonObject operator()();
6320b57cec5SDimitry Andric 
6330b57cec5SDimitry Andric   PythonObject operator()(std::initializer_list<PyObject *> args);
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric   PythonObject operator()(std::initializer_list<PythonObject> args);
6360b57cec5SDimitry Andric 
6370b57cec5SDimitry Andric   template <typename Arg, typename... Args>
6380b57cec5SDimitry Andric   PythonObject operator()(const Arg &arg, Args... args) {
6390b57cec5SDimitry Andric     return operator()({arg, args...});
6400b57cec5SDimitry Andric   }
6410b57cec5SDimitry Andric };
6420b57cec5SDimitry Andric 
6439dba64beSDimitry Andric class PythonFile : public TypedPythonObject<PythonFile> {
6440b57cec5SDimitry Andric public:
6459dba64beSDimitry Andric   using TypedPythonObject::TypedPythonObject;
6460b57cec5SDimitry Andric 
6479dba64beSDimitry Andric   PythonFile() : TypedPythonObject() {} // MSVC requires this for some reason
6480b57cec5SDimitry Andric 
6490b57cec5SDimitry Andric   static bool Check(PyObject *py_obj);
6500b57cec5SDimitry Andric 
6519dba64beSDimitry Andric   static llvm::Expected<PythonFile> FromFile(File &file,
6529dba64beSDimitry Andric                                              const char *mode = nullptr);
6530b57cec5SDimitry Andric 
6549dba64beSDimitry Andric   llvm::Expected<lldb::FileSP> ConvertToFile(bool borrowed = false);
6559dba64beSDimitry Andric   llvm::Expected<lldb::FileSP>
6569dba64beSDimitry Andric   ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed = false);
6570b57cec5SDimitry Andric };
6580b57cec5SDimitry Andric 
6599dba64beSDimitry Andric class PythonException : public llvm::ErrorInfo<PythonException> {
6609dba64beSDimitry Andric private:
6619dba64beSDimitry Andric   PyObject *m_exception_type, *m_exception, *m_traceback;
6629dba64beSDimitry Andric   PyObject *m_repr_bytes;
6639dba64beSDimitry Andric 
6649dba64beSDimitry Andric public:
6659dba64beSDimitry Andric   static char ID;
6669dba64beSDimitry Andric   const char *toCString() const;
6679dba64beSDimitry Andric   PythonException(const char *caller = nullptr);
6689dba64beSDimitry Andric   void Restore();
66981ad6265SDimitry Andric   ~PythonException() override;
6709dba64beSDimitry Andric   void log(llvm::raw_ostream &OS) const override;
6719dba64beSDimitry Andric   std::error_code convertToErrorCode() const override;
6729dba64beSDimitry Andric   bool Matches(PyObject *exc) const;
6739dba64beSDimitry Andric   std::string ReadBacktrace() const;
6749dba64beSDimitry Andric };
6759dba64beSDimitry Andric 
6769dba64beSDimitry Andric // This extracts the underlying T out of an Expected<T> and returns it.
6779dba64beSDimitry Andric // If the Expected is an Error instead of a T, that error will be converted
6789dba64beSDimitry Andric // into a python exception, and this will return a default-constructed T.
6799dba64beSDimitry Andric //
6809dba64beSDimitry Andric // This is appropriate for use right at the boundary of python calling into
6819dba64beSDimitry Andric // C++, such as in a SWIG typemap.   In such a context you should simply
6829dba64beSDimitry Andric // check if the returned T is valid, and if it is, return a NULL back
6839dba64beSDimitry Andric // to python.   This will result in the Error being raised as an exception
6849dba64beSDimitry Andric // from python code's point of view.
6859dba64beSDimitry Andric //
6869dba64beSDimitry Andric // For example:
6879dba64beSDimitry Andric // ```
6889dba64beSDimitry Andric // Expected<Foo *> efoop = some_cpp_function();
6899dba64beSDimitry Andric // Foo *foop = unwrapOrSetPythonException(efoop);
6909dba64beSDimitry Andric // if (!foop)
6919dba64beSDimitry Andric //    return NULL;
6929dba64beSDimitry Andric // do_something(*foop);
6939dba64beSDimitry Andric //
6949dba64beSDimitry Andric // If the Error returned was itself created because a python exception was
6959dba64beSDimitry Andric // raised when C++ code called into python, then the original exception
6969dba64beSDimitry Andric // will be restored.   Otherwise a simple string exception will be raised.
6979dba64beSDimitry Andric template <typename T> T unwrapOrSetPythonException(llvm::Expected<T> expected) {
6989dba64beSDimitry Andric   if (expected)
6999dba64beSDimitry Andric     return expected.get();
7009dba64beSDimitry Andric   llvm::handleAllErrors(
7019dba64beSDimitry Andric       expected.takeError(), [](PythonException &E) { E.Restore(); },
7029dba64beSDimitry Andric       [](const llvm::ErrorInfoBase &E) {
7039dba64beSDimitry Andric         PyErr_SetString(PyExc_Exception, E.message().c_str());
7049dba64beSDimitry Andric       });
7059dba64beSDimitry Andric   return T();
7069dba64beSDimitry Andric }
7079dba64beSDimitry Andric 
7089dba64beSDimitry Andric // This is only here to help incrementally migrate old, exception-unsafe
7099dba64beSDimitry Andric // code.
7109dba64beSDimitry Andric template <typename T> T unwrapIgnoringErrors(llvm::Expected<T> expected) {
7119dba64beSDimitry Andric   if (expected)
7129dba64beSDimitry Andric     return std::move(expected.get());
7139dba64beSDimitry Andric   llvm::consumeError(expected.takeError());
7149dba64beSDimitry Andric   return T();
7159dba64beSDimitry Andric }
7169dba64beSDimitry Andric 
7179dba64beSDimitry Andric llvm::Expected<PythonObject> runStringOneLine(const llvm::Twine &string,
7189dba64beSDimitry Andric                                               const PythonDictionary &globals,
7199dba64beSDimitry Andric                                               const PythonDictionary &locals);
7209dba64beSDimitry Andric 
7219dba64beSDimitry Andric llvm::Expected<PythonObject> runStringMultiLine(const llvm::Twine &string,
7229dba64beSDimitry Andric                                                 const PythonDictionary &globals,
7239dba64beSDimitry Andric                                                 const PythonDictionary &locals);
7249dba64beSDimitry Andric 
7259dba64beSDimitry Andric // Sometimes the best way to interact with a python interpreter is
7269dba64beSDimitry Andric // to run some python code.   You construct a PythonScript with
7279dba64beSDimitry Andric // script string.   The script assigns some function to `_function_`
7289dba64beSDimitry Andric // and you get a C++ callable object that calls the python function.
7299dba64beSDimitry Andric //
7309dba64beSDimitry Andric // Example:
7319dba64beSDimitry Andric //
7329dba64beSDimitry Andric // const char script[] = R"(
7339dba64beSDimitry Andric // def main(x, y):
7349dba64beSDimitry Andric //    ....
7359dba64beSDimitry Andric // )";
7369dba64beSDimitry Andric //
7379dba64beSDimitry Andric // Expected<PythonObject> cpp_foo_wrapper(PythonObject x, PythonObject y) {
7389dba64beSDimitry Andric //   // no need to synchronize access to this global, we already have the GIL
7399dba64beSDimitry Andric //   static PythonScript foo(script)
7409dba64beSDimitry Andric //   return  foo(x, y);
7419dba64beSDimitry Andric // }
7429dba64beSDimitry Andric class PythonScript {
7439dba64beSDimitry Andric   const char *script;
7449dba64beSDimitry Andric   PythonCallable function;
7459dba64beSDimitry Andric 
7469dba64beSDimitry Andric   llvm::Error Init();
7479dba64beSDimitry Andric 
7489dba64beSDimitry Andric public:
7499dba64beSDimitry Andric   PythonScript(const char *script) : script(script), function() {}
7509dba64beSDimitry Andric 
7519dba64beSDimitry Andric   template <typename... Args>
7529dba64beSDimitry Andric   llvm::Expected<PythonObject> operator()(Args &&... args) {
7539dba64beSDimitry Andric     if (llvm::Error error = Init())
7549dba64beSDimitry Andric       return std::move(error);
7559dba64beSDimitry Andric     return function.Call(std::forward<Args>(args)...);
7569dba64beSDimitry Andric   }
7579dba64beSDimitry Andric };
7589dba64beSDimitry Andric 
75904eeddc0SDimitry Andric class StructuredPythonObject : public StructuredData::Generic {
76004eeddc0SDimitry Andric public:
76104eeddc0SDimitry Andric   StructuredPythonObject() : StructuredData::Generic() {}
76204eeddc0SDimitry Andric 
76304eeddc0SDimitry Andric   // Take ownership of the object we received.
76404eeddc0SDimitry Andric   StructuredPythonObject(PythonObject obj)
76504eeddc0SDimitry Andric       : StructuredData::Generic(obj.release()) {}
76604eeddc0SDimitry Andric 
76704eeddc0SDimitry Andric   ~StructuredPythonObject() override {
76804eeddc0SDimitry Andric     // Hand ownership back to a (temporary) PythonObject instance and let it
76904eeddc0SDimitry Andric     // take care of releasing it.
77004eeddc0SDimitry Andric     PythonObject(PyRefType::Owned, static_cast<PyObject *>(GetValue()));
77104eeddc0SDimitry Andric   }
77204eeddc0SDimitry Andric 
77304eeddc0SDimitry Andric   bool IsValid() const override { return GetValue() && GetValue() != Py_None; }
77404eeddc0SDimitry Andric 
77504eeddc0SDimitry Andric   void Serialize(llvm::json::OStream &s) const override;
77604eeddc0SDimitry Andric 
77704eeddc0SDimitry Andric private:
77804eeddc0SDimitry Andric   StructuredPythonObject(const StructuredPythonObject &) = delete;
77904eeddc0SDimitry Andric   const StructuredPythonObject &
78004eeddc0SDimitry Andric   operator=(const StructuredPythonObject &) = delete;
78104eeddc0SDimitry Andric };
78204eeddc0SDimitry Andric 
7839dba64beSDimitry Andric } // namespace python
7840b57cec5SDimitry Andric } // namespace lldb_private
7850b57cec5SDimitry Andric 
7860b57cec5SDimitry Andric #endif
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
789