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 //
39d3bd5b3dSLawrence D'Anna // * Elimintate 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 
51d68983e3SPavel Labath #ifndef LLDB_DISABLE_PYTHON
52d68983e3SPavel Labath 
5341de9a97SKate Stone // LLDB Python header must be included first
5441de9a97SKate Stone #include "lldb-python.h"
5541de9a97SKate Stone 
569c40264fSZachary Turner #include "lldb/Host/File.h"
57f2a8bccfSPavel Labath #include "lldb/Utility/StructuredData.h"
582c1f46dcSZachary Turner 
595a72c02bSZachary Turner #include "llvm/ADT/ArrayRef.h"
605a72c02bSZachary Turner 
612c1f46dcSZachary Turner namespace lldb_private {
62*04edd189SLawrence D'Anna namespace python {
63edb35d95SEugene Zelenko 
64085328eeSLawrence D'Anna class PythonObject;
655a72c02bSZachary Turner class PythonBytes;
662c1f46dcSZachary Turner class PythonString;
672c1f46dcSZachary Turner class PythonList;
682c1f46dcSZachary Turner class PythonDictionary;
692c1f46dcSZachary Turner class PythonInteger;
70085328eeSLawrence D'Anna class PythonException;
712c1f46dcSZachary Turner 
72b9c1b51eSKate Stone class StructuredPythonObject : public StructuredData::Generic {
732c1f46dcSZachary Turner public:
74b9c1b51eSKate Stone   StructuredPythonObject() : StructuredData::Generic() {}
752c1f46dcSZachary Turner 
76b9c1b51eSKate Stone   StructuredPythonObject(void *obj) : StructuredData::Generic(obj) {
772c1f46dcSZachary Turner     Py_XINCREF(GetValue());
782c1f46dcSZachary Turner   }
792c1f46dcSZachary Turner 
80b9c1b51eSKate Stone   ~StructuredPythonObject() override {
812c1f46dcSZachary Turner     if (Py_IsInitialized())
822c1f46dcSZachary Turner       Py_XDECREF(GetValue());
832c1f46dcSZachary Turner     SetValue(nullptr);
842c1f46dcSZachary Turner   }
852c1f46dcSZachary Turner 
86b9c1b51eSKate Stone   bool IsValid() const override { return GetValue() && GetValue() != Py_None; }
872c1f46dcSZachary Turner 
882783d817SJonas Devlieghere   void Serialize(llvm::json::OStream &s) const override;
892c1f46dcSZachary Turner 
902c1f46dcSZachary Turner private:
912c1f46dcSZachary Turner   DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject);
922c1f46dcSZachary Turner };
932c1f46dcSZachary Turner 
94b9c1b51eSKate Stone enum class PyObjectType {
952c1f46dcSZachary Turner   Unknown,
962c1f46dcSZachary Turner   None,
97b81d715cSTatyana Krasnukha   Boolean,
982c1f46dcSZachary Turner   Integer,
992c1f46dcSZachary Turner   Dictionary,
1002c1f46dcSZachary Turner   List,
1019c40264fSZachary Turner   String,
1025a72c02bSZachary Turner   Bytes,
103f9d6d204SZachary Turner   ByteArray,
1047841efbbSZachary Turner   Module,
105a1405147SZachary Turner   Callable,
106a1405147SZachary Turner   Tuple,
1079c40264fSZachary Turner   File
1082c1f46dcSZachary Turner };
1092c1f46dcSZachary Turner 
110b9c1b51eSKate Stone enum class PyRefType {
111f8b22f8fSZachary Turner   Borrowed, // We are not given ownership of the incoming PyObject.
112f8b22f8fSZachary Turner             // We cannot safely hold it without calling Py_INCREF.
113f8b22f8fSZachary Turner   Owned     // We have ownership of the incoming PyObject.  We should
114f8b22f8fSZachary Turner             // not call Py_INCREF.
115f8b22f8fSZachary Turner };
116f8b22f8fSZachary Turner 
117085328eeSLawrence D'Anna 
118085328eeSLawrence D'Anna // Take a reference that you already own, and turn it into
119085328eeSLawrence D'Anna // a PythonObject.
120085328eeSLawrence D'Anna //
121085328eeSLawrence D'Anna // Most python API methods will return a +1 reference
122085328eeSLawrence D'Anna // if they succeed or NULL if and only if
123085328eeSLawrence D'Anna // they set an exception.   Use this to collect such return
124085328eeSLawrence D'Anna // values, after checking for NULL.
125085328eeSLawrence D'Anna //
126085328eeSLawrence D'Anna // If T is not just PythonObject, then obj must be already be
127085328eeSLawrence D'Anna // checked to be of the correct type.
128085328eeSLawrence D'Anna template <typename T> T Take(PyObject *obj) {
129085328eeSLawrence D'Anna   assert(obj);
130085328eeSLawrence D'Anna   assert(!PyErr_Occurred());
131085328eeSLawrence D'Anna   T thing(PyRefType::Owned, obj);
132085328eeSLawrence D'Anna   assert(thing.IsValid());
133085328eeSLawrence D'Anna   return std::move(thing);
134085328eeSLawrence D'Anna }
135085328eeSLawrence D'Anna 
136085328eeSLawrence D'Anna // Retain a reference you have borrowed, and turn it into
137085328eeSLawrence D'Anna // a PythonObject.
138085328eeSLawrence D'Anna //
139085328eeSLawrence D'Anna // A minority of python APIs return a borrowed reference
140085328eeSLawrence D'Anna // instead of a +1.   They will also return NULL if and only
141085328eeSLawrence D'Anna // if they set an exception.   Use this to collect such return
142085328eeSLawrence D'Anna // values, after checking for NULL.
143085328eeSLawrence D'Anna //
144085328eeSLawrence D'Anna // If T is not just PythonObject, then obj must be already be
145085328eeSLawrence D'Anna // checked to be of the correct type.
146085328eeSLawrence D'Anna template <typename T> T Retain(PyObject *obj) {
147085328eeSLawrence D'Anna   assert(obj);
148085328eeSLawrence D'Anna   assert(!PyErr_Occurred());
149085328eeSLawrence D'Anna   T thing(PyRefType::Borrowed, obj);
150085328eeSLawrence D'Anna   assert(thing.IsValid());
151085328eeSLawrence D'Anna   return std::move(thing);
152085328eeSLawrence D'Anna }
153085328eeSLawrence D'Anna 
154722b6189SLawrence D'Anna // This class can be used like a utility function to convert from
155722b6189SLawrence D'Anna // a llvm-friendly Twine into a null-terminated const char *,
156722b6189SLawrence D'Anna // which is the form python C APIs want their strings in.
157722b6189SLawrence D'Anna //
158722b6189SLawrence D'Anna // Example:
159722b6189SLawrence D'Anna // const llvm::Twine &some_twine;
160722b6189SLawrence D'Anna // PyFoo_Bar(x, y, z, NullTerminated(some_twine));
161722b6189SLawrence D'Anna //
162722b6189SLawrence D'Anna // Why a class instead of a function?  If the twine isn't already null
163722b6189SLawrence D'Anna // terminated, it will need a temporary buffer to copy the string
164722b6189SLawrence D'Anna // into.   We need that buffer to stick around for the lifetime of the
165722b6189SLawrence D'Anna // statement.
166722b6189SLawrence D'Anna class NullTerminated {
167722b6189SLawrence D'Anna   const char *str;
168722b6189SLawrence D'Anna   llvm::SmallString<32> storage;
169722b6189SLawrence D'Anna 
170722b6189SLawrence D'Anna public:
171722b6189SLawrence D'Anna   NullTerminated(const llvm::Twine &twine) {
172722b6189SLawrence D'Anna     llvm::StringRef ref = twine.toNullTerminatedStringRef(storage);
173722b6189SLawrence D'Anna     str = ref.begin();
174722b6189SLawrence D'Anna   }
175722b6189SLawrence D'Anna   operator const char *() { return str; }
176722b6189SLawrence D'Anna };
177722b6189SLawrence D'Anna 
178*04edd189SLawrence D'Anna inline llvm::Error nullDeref() {
179*04edd189SLawrence D'Anna   return llvm::createStringError(llvm::inconvertibleErrorCode(),
180*04edd189SLawrence D'Anna                                  "A NULL PyObject* was dereferenced");
181*04edd189SLawrence D'Anna }
182*04edd189SLawrence D'Anna 
183*04edd189SLawrence D'Anna inline llvm::Error exception(const char *s = nullptr) {
184*04edd189SLawrence D'Anna   return llvm::make_error<PythonException>(s);
185*04edd189SLawrence D'Anna }
186*04edd189SLawrence D'Anna 
187*04edd189SLawrence D'Anna inline llvm::Error keyError() {
188*04edd189SLawrence D'Anna   return llvm::createStringError(llvm::inconvertibleErrorCode(),
189*04edd189SLawrence D'Anna                                  "key not in dict");
190*04edd189SLawrence D'Anna }
191085328eeSLawrence D'Anna 
192b9c1b51eSKate Stone enum class PyInitialValue { Invalid, Empty };
193f8b22f8fSZachary Turner 
194085328eeSLawrence D'Anna template <typename T, typename Enable = void> struct PythonFormat;
195085328eeSLawrence D'Anna 
196085328eeSLawrence D'Anna template <> struct PythonFormat<unsigned long long> {
197085328eeSLawrence D'Anna   static constexpr char format = 'K';
198085328eeSLawrence D'Anna   static auto get(unsigned long long value) { return value; }
199085328eeSLawrence D'Anna };
200085328eeSLawrence D'Anna 
201085328eeSLawrence D'Anna template <> struct PythonFormat<long long> {
202085328eeSLawrence D'Anna   static constexpr char format = 'L';
203085328eeSLawrence D'Anna   static auto get(long long value) { return value; }
204085328eeSLawrence D'Anna };
205085328eeSLawrence D'Anna 
206*04edd189SLawrence D'Anna template <> struct PythonFormat<PyObject *> {
207*04edd189SLawrence D'Anna   static constexpr char format = 'O';
208*04edd189SLawrence D'Anna   static auto get(PyObject *value) { return value; }
209*04edd189SLawrence D'Anna };
210*04edd189SLawrence D'Anna 
211085328eeSLawrence D'Anna template <typename T>
212085328eeSLawrence D'Anna struct PythonFormat<
213085328eeSLawrence D'Anna     T, typename std::enable_if<std::is_base_of<PythonObject, T>::value>::type> {
214085328eeSLawrence D'Anna   static constexpr char format = 'O';
215085328eeSLawrence D'Anna   static auto get(const T &value) { return value.get(); }
216085328eeSLawrence D'Anna };
217085328eeSLawrence D'Anna 
218b9c1b51eSKate Stone class PythonObject {
2192c1f46dcSZachary Turner public:
220b9c1b51eSKate Stone   PythonObject() : m_py_obj(nullptr) {}
2212c1f46dcSZachary Turner 
222*04edd189SLawrence D'Anna   PythonObject(PyRefType type, PyObject *py_obj) {
223*04edd189SLawrence D'Anna     m_py_obj = py_obj;
224*04edd189SLawrence D'Anna     // If this is a borrowed reference, we need to convert it to
225*04edd189SLawrence D'Anna     // an owned reference by incrementing it.  If it is an owned
226*04edd189SLawrence D'Anna     // reference (for example the caller allocated it with PyDict_New()
227*04edd189SLawrence D'Anna     // then we must *not* increment it.
228*04edd189SLawrence D'Anna     if (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed)
229*04edd189SLawrence D'Anna       Py_XINCREF(m_py_obj);
2302c1f46dcSZachary Turner   }
2312c1f46dcSZachary Turner 
23203819d1cSLawrence D'Anna   PythonObject(const PythonObject &rhs)
23303819d1cSLawrence D'Anna       : PythonObject(PyRefType::Borrowed, rhs.m_py_obj) {}
2342c1f46dcSZachary Turner 
235085328eeSLawrence D'Anna   PythonObject(PythonObject &&rhs) {
236085328eeSLawrence D'Anna     m_py_obj = rhs.m_py_obj;
237085328eeSLawrence D'Anna     rhs.m_py_obj = nullptr;
238085328eeSLawrence D'Anna   }
239085328eeSLawrence D'Anna 
240d3bd5b3dSLawrence D'Anna   ~PythonObject() { Reset(); }
2412c1f46dcSZachary Turner 
242b9c1b51eSKate Stone   void Reset() {
243085328eeSLawrence D'Anna     if (m_py_obj && Py_IsInitialized())
244085328eeSLawrence D'Anna       Py_DECREF(m_py_obj);
245f8b22f8fSZachary Turner     m_py_obj = nullptr;
2462c1f46dcSZachary Turner   }
247f8b22f8fSZachary Turner 
248b9c1b51eSKate Stone   void Dump() const {
2492c1f46dcSZachary Turner     if (m_py_obj)
2502c1f46dcSZachary Turner       _PyObject_Dump(m_py_obj);
2512c1f46dcSZachary Turner     else
2522c1f46dcSZachary Turner       puts("NULL");
2532c1f46dcSZachary Turner   }
2542c1f46dcSZachary Turner 
255b9c1b51eSKate Stone   void Dump(Stream &strm) const;
2562c1f46dcSZachary Turner 
257b9c1b51eSKate Stone   PyObject *get() const { return m_py_obj; }
2582c1f46dcSZachary Turner 
259b9c1b51eSKate Stone   PyObject *release() {
26060c24f70SZachary Turner     PyObject *result = m_py_obj;
26160c24f70SZachary Turner     m_py_obj = nullptr;
26260c24f70SZachary Turner     return result;
26360c24f70SZachary Turner   }
26460c24f70SZachary Turner 
26503819d1cSLawrence D'Anna   PythonObject &operator=(PythonObject other) {
266085328eeSLawrence D'Anna     Reset();
26703819d1cSLawrence D'Anna     m_py_obj = std::exchange(other.m_py_obj, nullptr);
268085328eeSLawrence D'Anna     return *this;
269085328eeSLawrence D'Anna   }
270085328eeSLawrence D'Anna 
271b9c1b51eSKate Stone   PyObjectType GetObjectType() const;
2727841efbbSZachary Turner 
273b9c1b51eSKate Stone   PythonString Repr() const;
2747841efbbSZachary Turner 
275b9c1b51eSKate Stone   PythonString Str() const;
2767841efbbSZachary Turner 
277b9c1b51eSKate Stone   static PythonObject ResolveNameWithDictionary(llvm::StringRef name,
278b9c1b51eSKate Stone                                                 const PythonDictionary &dict);
2797841efbbSZachary Turner 
280b58fb2f4SZachary Turner   template <typename T>
281b9c1b51eSKate Stone   static T ResolveNameWithDictionary(llvm::StringRef name,
282b9c1b51eSKate Stone                                      const PythonDictionary &dict) {
283b58fb2f4SZachary Turner     return ResolveNameWithDictionary(name, dict).AsType<T>();
284b58fb2f4SZachary Turner   }
285b58fb2f4SZachary Turner 
286b9c1b51eSKate Stone   PythonObject ResolveName(llvm::StringRef name) const;
2877841efbbSZachary Turner 
288b9c1b51eSKate Stone   template <typename T> T ResolveName(llvm::StringRef name) const {
289b58fb2f4SZachary Turner     return ResolveName(name).AsType<T>();
290b58fb2f4SZachary Turner   }
291b58fb2f4SZachary Turner 
292b9c1b51eSKate Stone   bool HasAttribute(llvm::StringRef attribute) const;
2939c40264fSZachary Turner 
294b9c1b51eSKate Stone   PythonObject GetAttributeValue(llvm::StringRef attribute) const;
2957d6d218eSZachary Turner 
296085328eeSLawrence D'Anna   bool IsNone() const { return m_py_obj == Py_None; }
297f8b22f8fSZachary Turner 
298085328eeSLawrence D'Anna   bool IsValid() const { return m_py_obj != nullptr; }
299f8b22f8fSZachary Turner 
300085328eeSLawrence D'Anna   bool IsAllocated() const { return IsValid() && !IsNone(); }
301085328eeSLawrence D'Anna 
302085328eeSLawrence D'Anna   explicit operator bool() const { return IsValid() && !IsNone(); }
3032c1f46dcSZachary Turner 
304b9c1b51eSKate Stone   template <typename T> T AsType() const {
3057d6d218eSZachary Turner     if (!T::Check(m_py_obj))
3067d6d218eSZachary Turner       return T();
3077d6d218eSZachary Turner     return T(PyRefType::Borrowed, m_py_obj);
3087d6d218eSZachary Turner   }
3097d6d218eSZachary Turner 
310b9c1b51eSKate Stone   StructuredData::ObjectSP CreateStructuredObject() const;
3112c1f46dcSZachary Turner 
3122c1f46dcSZachary Turner protected:
313c86a6acaSLawrence D'Anna 
314c86a6acaSLawrence D'Anna #if PY_MAJOR_VERSION < 3
315c86a6acaSLawrence D'Anna   // The python 2 API declares some arguments as char* that should
316c86a6acaSLawrence D'Anna   // be const char *, but it doesn't actually modify them.
317c86a6acaSLawrence D'Anna   static char *py2_const_cast(const char *s) { return const_cast<char *>(s); }
318c86a6acaSLawrence D'Anna #else
319c86a6acaSLawrence D'Anna   static const char *py2_const_cast(const char *s) { return s; }
320c86a6acaSLawrence D'Anna #endif
321085328eeSLawrence D'Anna 
322085328eeSLawrence D'Anna public:
323085328eeSLawrence D'Anna   template <typename... T>
324085328eeSLawrence D'Anna   llvm::Expected<PythonObject> CallMethod(const char *name,
325085328eeSLawrence D'Anna                                           const T &... t) const {
326085328eeSLawrence D'Anna     const char format[] = {'(', PythonFormat<T>::format..., ')', 0};
327085328eeSLawrence D'Anna     PyObject *obj =
328c86a6acaSLawrence D'Anna         PyObject_CallMethod(m_py_obj, py2_const_cast(name),
329c86a6acaSLawrence D'Anna                             py2_const_cast(format), PythonFormat<T>::get(t)...);
330c86a6acaSLawrence D'Anna     if (!obj)
331c86a6acaSLawrence D'Anna       return exception();
332c86a6acaSLawrence D'Anna     return python::Take<PythonObject>(obj);
333c86a6acaSLawrence D'Anna   }
334c86a6acaSLawrence D'Anna 
335c86a6acaSLawrence D'Anna   template <typename... T>
336c86a6acaSLawrence D'Anna   llvm::Expected<PythonObject> Call(const T &... t) const {
337c86a6acaSLawrence D'Anna     const char format[] = {'(', PythonFormat<T>::format..., ')', 0};
338c86a6acaSLawrence D'Anna     PyObject *obj = PyObject_CallFunction(m_py_obj, py2_const_cast(format),
339c86a6acaSLawrence D'Anna                                           PythonFormat<T>::get(t)...);
340085328eeSLawrence D'Anna     if (!obj)
341085328eeSLawrence D'Anna       return exception();
342085328eeSLawrence D'Anna     return python::Take<PythonObject>(obj);
343085328eeSLawrence D'Anna   }
344085328eeSLawrence D'Anna 
345722b6189SLawrence D'Anna   llvm::Expected<PythonObject> GetAttribute(const llvm::Twine &name) const {
346085328eeSLawrence D'Anna     if (!m_py_obj)
347085328eeSLawrence D'Anna       return nullDeref();
348722b6189SLawrence D'Anna     PyObject *obj = PyObject_GetAttrString(m_py_obj, NullTerminated(name));
349085328eeSLawrence D'Anna     if (!obj)
350085328eeSLawrence D'Anna       return exception();
351085328eeSLawrence D'Anna     return python::Take<PythonObject>(obj);
352085328eeSLawrence D'Anna   }
353085328eeSLawrence D'Anna 
354085328eeSLawrence D'Anna   llvm::Expected<bool> IsTrue() {
355085328eeSLawrence D'Anna     if (!m_py_obj)
356085328eeSLawrence D'Anna       return nullDeref();
357085328eeSLawrence D'Anna     int r = PyObject_IsTrue(m_py_obj);
358085328eeSLawrence D'Anna     if (r < 0)
359085328eeSLawrence D'Anna       return exception();
360085328eeSLawrence D'Anna     return !!r;
361085328eeSLawrence D'Anna   }
362085328eeSLawrence D'Anna 
363085328eeSLawrence D'Anna   llvm::Expected<long long> AsLongLong() {
364085328eeSLawrence D'Anna     if (!m_py_obj)
365085328eeSLawrence D'Anna       return nullDeref();
366085328eeSLawrence D'Anna     assert(!PyErr_Occurred());
367085328eeSLawrence D'Anna     long long r = PyLong_AsLongLong(m_py_obj);
368085328eeSLawrence D'Anna     if (PyErr_Occurred())
369085328eeSLawrence D'Anna       return exception();
370085328eeSLawrence D'Anna     return r;
371085328eeSLawrence D'Anna   }
372085328eeSLawrence D'Anna 
373085328eeSLawrence D'Anna   llvm::Expected<bool> IsInstance(const PythonObject &cls) {
374085328eeSLawrence D'Anna     if (!m_py_obj || !cls.IsValid())
375085328eeSLawrence D'Anna       return nullDeref();
376085328eeSLawrence D'Anna     int r = PyObject_IsInstance(m_py_obj, cls.get());
377085328eeSLawrence D'Anna     if (r < 0)
378085328eeSLawrence D'Anna       return exception();
379085328eeSLawrence D'Anna     return !!r;
380085328eeSLawrence D'Anna   }
381085328eeSLawrence D'Anna 
382085328eeSLawrence D'Anna protected:
3832c1f46dcSZachary Turner   PyObject *m_py_obj;
3842c1f46dcSZachary Turner };
3852c1f46dcSZachary Turner 
386085328eeSLawrence D'Anna 
387085328eeSLawrence D'Anna // This is why C++ needs monads.
388085328eeSLawrence D'Anna template <typename T> llvm::Expected<T> As(llvm::Expected<PythonObject> &&obj) {
389085328eeSLawrence D'Anna   if (!obj)
390085328eeSLawrence D'Anna     return obj.takeError();
391085328eeSLawrence D'Anna   if (!T::Check(obj.get().get()))
392085328eeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
393085328eeSLawrence D'Anna                                    "type error");
394085328eeSLawrence D'Anna   return T(PyRefType::Borrowed, std::move(obj.get().get()));
395085328eeSLawrence D'Anna }
396085328eeSLawrence D'Anna 
397085328eeSLawrence D'Anna template <> llvm::Expected<bool> As<bool>(llvm::Expected<PythonObject> &&obj);
398085328eeSLawrence D'Anna 
399085328eeSLawrence D'Anna template <>
400085328eeSLawrence D'Anna llvm::Expected<long long> As<long long>(llvm::Expected<PythonObject> &&obj);
401085328eeSLawrence D'Anna 
402c86a6acaSLawrence D'Anna template <>
403c86a6acaSLawrence D'Anna llvm::Expected<std::string> As<std::string>(llvm::Expected<PythonObject> &&obj);
404c86a6acaSLawrence D'Anna 
405085328eeSLawrence D'Anna 
406d3bd5b3dSLawrence D'Anna template <class T> class TypedPythonObject : public PythonObject {
4075a72c02bSZachary Turner public:
408d3bd5b3dSLawrence D'Anna   // override to perform implicit type conversions on Reset
409d3bd5b3dSLawrence D'Anna   // This can be eliminated once we drop python 2 support.
410d3bd5b3dSLawrence D'Anna   static void Convert(PyRefType &type, PyObject *&py_obj) {}
411d3bd5b3dSLawrence D'Anna 
412722b6189SLawrence D'Anna   TypedPythonObject(PyRefType type, PyObject *py_obj) {
413d3bd5b3dSLawrence D'Anna     if (!py_obj)
414d3bd5b3dSLawrence D'Anna       return;
415d3bd5b3dSLawrence D'Anna     T::Convert(type, py_obj);
416d3bd5b3dSLawrence D'Anna     if (T::Check(py_obj))
417*04edd189SLawrence D'Anna       PythonObject::operator=(PythonObject(type, py_obj));
418d3bd5b3dSLawrence D'Anna     else if (type == PyRefType::Owned)
419d3bd5b3dSLawrence D'Anna       Py_DECREF(py_obj);
420d3bd5b3dSLawrence D'Anna   }
421d3bd5b3dSLawrence D'Anna 
422d3bd5b3dSLawrence D'Anna   TypedPythonObject() {}
423d3bd5b3dSLawrence D'Anna };
424d3bd5b3dSLawrence D'Anna 
425d3bd5b3dSLawrence D'Anna class PythonBytes : public TypedPythonObject<PythonBytes> {
426d3bd5b3dSLawrence D'Anna public:
427d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
4285a72c02bSZachary Turner   explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes);
4295a72c02bSZachary Turner   PythonBytes(const uint8_t *bytes, size_t length);
4305a72c02bSZachary Turner 
431b9c1b51eSKate Stone   static bool Check(PyObject *py_obj);
4325a72c02bSZachary Turner 
433b9c1b51eSKate Stone   llvm::ArrayRef<uint8_t> GetBytes() const;
4345a72c02bSZachary Turner 
435b9c1b51eSKate Stone   size_t GetSize() const;
4365a72c02bSZachary Turner 
437b9c1b51eSKate Stone   void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
4385a72c02bSZachary Turner 
439b9c1b51eSKate Stone   StructuredData::StringSP CreateStructuredString() const;
4405a72c02bSZachary Turner };
4415a72c02bSZachary Turner 
442d3bd5b3dSLawrence D'Anna class PythonByteArray : public TypedPythonObject<PythonByteArray> {
443f9d6d204SZachary Turner public:
444d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
445f9d6d204SZachary Turner   explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes);
446f9d6d204SZachary Turner   PythonByteArray(const uint8_t *bytes, size_t length);
447f9d6d204SZachary Turner   PythonByteArray(const PythonBytes &object);
448f9d6d204SZachary Turner 
449b9c1b51eSKate Stone   static bool Check(PyObject *py_obj);
450f9d6d204SZachary Turner 
451b9c1b51eSKate Stone   llvm::ArrayRef<uint8_t> GetBytes() const;
452f9d6d204SZachary Turner 
453b9c1b51eSKate Stone   size_t GetSize() const;
454f9d6d204SZachary Turner 
455b9c1b51eSKate Stone   void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
456f9d6d204SZachary Turner 
457b9c1b51eSKate Stone   StructuredData::StringSP CreateStructuredString() const;
458f9d6d204SZachary Turner };
459f9d6d204SZachary Turner 
460d3bd5b3dSLawrence D'Anna class PythonString : public TypedPythonObject<PythonString> {
4612c1f46dcSZachary Turner public:
462d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
463085328eeSLawrence D'Anna   static llvm::Expected<PythonString> FromUTF8(llvm::StringRef string);
464085328eeSLawrence D'Anna 
465d3bd5b3dSLawrence D'Anna   PythonString() : TypedPythonObject() {} // MSVC requires this for some reason
466edb35d95SEugene Zelenko 
467d3bd5b3dSLawrence D'Anna   explicit PythonString(llvm::StringRef string); // safe, null on error
4682c1f46dcSZachary Turner 
46922c8efcdSZachary Turner   static bool Check(PyObject *py_obj);
470d3bd5b3dSLawrence D'Anna   static void Convert(PyRefType &type, PyObject *&py_obj);
4712c1f46dcSZachary Turner 
472085328eeSLawrence D'Anna   llvm::StringRef GetString() const; // safe, empty string on error
473085328eeSLawrence D'Anna 
474085328eeSLawrence D'Anna   llvm::Expected<llvm::StringRef> AsUTF8() const;
4752c1f46dcSZachary Turner 
476b9c1b51eSKate Stone   size_t GetSize() const;
4772c1f46dcSZachary Turner 
478085328eeSLawrence D'Anna   void SetString(llvm::StringRef string); // safe, null on error
4792c1f46dcSZachary Turner 
4802c1f46dcSZachary Turner   StructuredData::StringSP CreateStructuredString() const;
4812c1f46dcSZachary Turner };
4822c1f46dcSZachary Turner 
483d3bd5b3dSLawrence D'Anna class PythonInteger : public TypedPythonObject<PythonInteger> {
4842c1f46dcSZachary Turner public:
485d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
486edb35d95SEugene Zelenko 
487d3bd5b3dSLawrence D'Anna   PythonInteger() : TypedPythonObject() {} // MSVC requires this for some reason
488d3bd5b3dSLawrence D'Anna 
489d3bd5b3dSLawrence D'Anna   explicit PythonInteger(int64_t value);
4902c1f46dcSZachary Turner 
49122c8efcdSZachary Turner   static bool Check(PyObject *py_obj);
492d3bd5b3dSLawrence D'Anna   static void Convert(PyRefType &type, PyObject *&py_obj);
4932c1f46dcSZachary Turner 
4942c1f46dcSZachary Turner   int64_t GetInteger() const;
4952c1f46dcSZachary Turner 
496b9c1b51eSKate Stone   void SetInteger(int64_t value);
4972c1f46dcSZachary Turner 
4982c1f46dcSZachary Turner   StructuredData::IntegerSP CreateStructuredInteger() const;
4992c1f46dcSZachary Turner };
5002c1f46dcSZachary Turner 
501d3bd5b3dSLawrence D'Anna class PythonBoolean : public TypedPythonObject<PythonBoolean> {
502b81d715cSTatyana Krasnukha public:
503d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
504b81d715cSTatyana Krasnukha 
505d3bd5b3dSLawrence D'Anna   explicit PythonBoolean(bool value);
506b81d715cSTatyana Krasnukha 
507b81d715cSTatyana Krasnukha   static bool Check(PyObject *py_obj);
508b81d715cSTatyana Krasnukha 
509b81d715cSTatyana Krasnukha   bool GetValue() const;
510b81d715cSTatyana Krasnukha 
511b81d715cSTatyana Krasnukha   void SetValue(bool value);
512b81d715cSTatyana Krasnukha 
513b81d715cSTatyana Krasnukha   StructuredData::BooleanSP CreateStructuredBoolean() const;
514b81d715cSTatyana Krasnukha };
515b81d715cSTatyana Krasnukha 
516d3bd5b3dSLawrence D'Anna class PythonList : public TypedPythonObject<PythonList> {
5172c1f46dcSZachary Turner public:
518d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
519d3bd5b3dSLawrence D'Anna 
520d3bd5b3dSLawrence D'Anna   PythonList() : TypedPythonObject() {} // MSVC requires this for some reason
521d3bd5b3dSLawrence D'Anna 
52287f47729SZachary Turner   explicit PythonList(PyInitialValue value);
52387f47729SZachary Turner   explicit PythonList(int list_size);
5242c1f46dcSZachary Turner 
52522c8efcdSZachary Turner   static bool Check(PyObject *py_obj);
52622c8efcdSZachary Turner 
5272c1f46dcSZachary Turner   uint32_t GetSize() const;
5282c1f46dcSZachary Turner 
5292c1f46dcSZachary Turner   PythonObject GetItemAtIndex(uint32_t index) const;
5302c1f46dcSZachary Turner 
531f8b22f8fSZachary Turner   void SetItemAtIndex(uint32_t index, const PythonObject &object);
5322c1f46dcSZachary Turner 
533f8b22f8fSZachary Turner   void AppendItem(const PythonObject &object);
5342c1f46dcSZachary Turner 
5352c1f46dcSZachary Turner   StructuredData::ArraySP CreateStructuredArray() const;
5362c1f46dcSZachary Turner };
5372c1f46dcSZachary Turner 
538d3bd5b3dSLawrence D'Anna class PythonTuple : public TypedPythonObject<PythonTuple> {
539a1405147SZachary Turner public:
540d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
541d3bd5b3dSLawrence D'Anna 
542a1405147SZachary Turner   explicit PythonTuple(PyInitialValue value);
543a1405147SZachary Turner   explicit PythonTuple(int tuple_size);
544a1405147SZachary Turner   PythonTuple(std::initializer_list<PythonObject> objects);
545a1405147SZachary Turner   PythonTuple(std::initializer_list<PyObject *> objects);
546a1405147SZachary Turner 
547a1405147SZachary Turner   static bool Check(PyObject *py_obj);
548a1405147SZachary Turner 
549a1405147SZachary Turner   uint32_t GetSize() const;
550a1405147SZachary Turner 
551a1405147SZachary Turner   PythonObject GetItemAtIndex(uint32_t index) const;
552a1405147SZachary Turner 
553a1405147SZachary Turner   void SetItemAtIndex(uint32_t index, const PythonObject &object);
554a1405147SZachary Turner 
555a1405147SZachary Turner   StructuredData::ArraySP CreateStructuredArray() const;
556a1405147SZachary Turner };
557a1405147SZachary Turner 
558d3bd5b3dSLawrence D'Anna class PythonDictionary : public TypedPythonObject<PythonDictionary> {
5592c1f46dcSZachary Turner public:
560d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
561edb35d95SEugene Zelenko 
562d3bd5b3dSLawrence D'Anna   PythonDictionary() : TypedPythonObject() {} // MSVC requires this for some reason
563d3bd5b3dSLawrence D'Anna 
564d3bd5b3dSLawrence D'Anna   explicit PythonDictionary(PyInitialValue value);
5652c1f46dcSZachary Turner 
56622c8efcdSZachary Turner   static bool Check(PyObject *py_obj);
56722c8efcdSZachary Turner 
5682c1f46dcSZachary Turner   uint32_t GetSize() const;
5692c1f46dcSZachary Turner 
570f8b22f8fSZachary Turner   PythonList GetKeys() const;
5712c1f46dcSZachary Turner 
572c86a6acaSLawrence D'Anna   PythonObject GetItemForKey(const PythonObject &key) const; // DEPRECATED
573c86a6acaSLawrence D'Anna   void SetItemForKey(const PythonObject &key,
574c86a6acaSLawrence D'Anna                      const PythonObject &value); // DEPRECATED
575c86a6acaSLawrence D'Anna 
576c86a6acaSLawrence D'Anna   llvm::Expected<PythonObject> GetItem(const PythonObject &key) const;
577722b6189SLawrence D'Anna   llvm::Expected<PythonObject> GetItem(const llvm::Twine &key) const;
578c86a6acaSLawrence D'Anna   llvm::Error SetItem(const PythonObject &key, const PythonObject &value) const;
579722b6189SLawrence D'Anna   llvm::Error SetItem(const llvm::Twine &key, const PythonObject &value) const;
5802c1f46dcSZachary Turner 
5812c1f46dcSZachary Turner   StructuredData::DictionarySP CreateStructuredDictionary() const;
5822c1f46dcSZachary Turner };
58387f47729SZachary Turner 
584d3bd5b3dSLawrence D'Anna class PythonModule : public TypedPythonObject<PythonModule> {
5857841efbbSZachary Turner public:
586d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
5877841efbbSZachary Turner 
5887841efbbSZachary Turner   static bool Check(PyObject *py_obj);
5897841efbbSZachary Turner 
590b9c1b51eSKate Stone   static PythonModule BuiltinsModule();
591a1405147SZachary Turner 
592b9c1b51eSKate Stone   static PythonModule MainModule();
593a1405147SZachary Turner 
594b9c1b51eSKate Stone   static PythonModule AddModule(llvm::StringRef module);
5957841efbbSZachary Turner 
596085328eeSLawrence D'Anna   // safe, returns invalid on error;
597085328eeSLawrence D'Anna   static PythonModule ImportModule(llvm::StringRef name) {
598085328eeSLawrence D'Anna     std::string s = name;
599085328eeSLawrence D'Anna     auto mod = Import(s.c_str());
600085328eeSLawrence D'Anna     if (!mod) {
601085328eeSLawrence D'Anna       llvm::consumeError(mod.takeError());
602085328eeSLawrence D'Anna       return PythonModule();
603085328eeSLawrence D'Anna     }
604085328eeSLawrence D'Anna     return std::move(mod.get());
605085328eeSLawrence D'Anna   }
606085328eeSLawrence D'Anna 
607722b6189SLawrence D'Anna   static llvm::Expected<PythonModule> Import(const llvm::Twine &name);
608085328eeSLawrence D'Anna 
609722b6189SLawrence D'Anna   llvm::Expected<PythonObject> Get(const llvm::Twine &name);
6102419f1d5SZachary Turner 
6117841efbbSZachary Turner   PythonDictionary GetDictionary() const;
6127841efbbSZachary Turner };
6137841efbbSZachary Turner 
614d3bd5b3dSLawrence D'Anna class PythonCallable : public TypedPythonObject<PythonCallable> {
615a1405147SZachary Turner public:
616d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
617d3bd5b3dSLawrence D'Anna 
618b58fb2f4SZachary Turner   struct ArgInfo {
6192386537cSLawrence D'Anna     /* the largest number of positional arguments this callable
6202386537cSLawrence D'Anna      * can accept, or UNBOUNDED, ie UINT_MAX if it's a varargs
6212386537cSLawrence D'Anna      * function and can accept an arbitrary number */
6222386537cSLawrence D'Anna     unsigned max_positional_args;
6232386537cSLawrence D'Anna     static constexpr unsigned UNBOUNDED = UINT_MAX; // FIXME c++17 inline
624c86a6acaSLawrence D'Anna     /* the number of positional arguments, including optional ones,
625c86a6acaSLawrence D'Anna      * and excluding varargs.  If this is a bound method, then the
626c86a6acaSLawrence D'Anna      * count will still include a +1 for self.
627c86a6acaSLawrence D'Anna      *
628c86a6acaSLawrence D'Anna      * FIXME. That's crazy.  This should be replaced with
629c86a6acaSLawrence D'Anna      * an accurate min and max for positional args.
630c86a6acaSLawrence D'Anna      */
631c86a6acaSLawrence D'Anna     int count;
632c86a6acaSLawrence D'Anna     /* does the callable have positional varargs? */
633c86a6acaSLawrence D'Anna     bool has_varargs : 1; // FIXME delete this
634b58fb2f4SZachary Turner   };
635b58fb2f4SZachary Turner 
636b9c1b51eSKate Stone   static bool Check(PyObject *py_obj);
637a1405147SZachary Turner 
638c86a6acaSLawrence D'Anna   llvm::Expected<ArgInfo> GetArgInfo() const;
639c86a6acaSLawrence D'Anna 
640c86a6acaSLawrence D'Anna   llvm::Expected<ArgInfo> GetInitArgInfo() const;
641c86a6acaSLawrence D'Anna 
642c86a6acaSLawrence D'Anna   ArgInfo GetNumArguments() const; // DEPRECATED
64327a14f19SJim Ingham 
64427a14f19SJim Ingham   // If the callable is a Py_Class, then find the number of arguments
64527a14f19SJim Ingham   // of the __init__ method.
646c86a6acaSLawrence D'Anna   ArgInfo GetNumInitArguments() const; // DEPRECATED
647b58fb2f4SZachary Turner 
648b9c1b51eSKate Stone   PythonObject operator()();
649a1405147SZachary Turner 
650b9c1b51eSKate Stone   PythonObject operator()(std::initializer_list<PyObject *> args);
651a1405147SZachary Turner 
652b9c1b51eSKate Stone   PythonObject operator()(std::initializer_list<PythonObject> args);
653b58fb2f4SZachary Turner 
654b58fb2f4SZachary Turner   template <typename Arg, typename... Args>
655b9c1b51eSKate Stone   PythonObject operator()(const Arg &arg, Args... args) {
656b58fb2f4SZachary Turner     return operator()({arg, args...});
657b58fb2f4SZachary Turner   }
658a1405147SZachary Turner };
659a1405147SZachary Turner 
660d3bd5b3dSLawrence D'Anna class PythonFile : public TypedPythonObject<PythonFile> {
6619c40264fSZachary Turner public:
662d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
663edb35d95SEugene Zelenko 
664d3bd5b3dSLawrence D'Anna   PythonFile() : TypedPythonObject() {} // MSVC requires this for some reason
6659c40264fSZachary Turner 
6669c40264fSZachary Turner   static bool Check(PyObject *py_obj);
6679c40264fSZachary Turner 
668d9b553ecSLawrence D'Anna   static llvm::Expected<PythonFile> FromFile(File &file,
669d9b553ecSLawrence D'Anna                                              const char *mode = nullptr);
670d9b553ecSLawrence D'Anna 
671085328eeSLawrence D'Anna   llvm::Expected<lldb::FileSP> ConvertToFile(bool borrowed = false);
672085328eeSLawrence D'Anna   llvm::Expected<lldb::FileSP>
673085328eeSLawrence D'Anna   ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed = false);
6749c40264fSZachary Turner };
6759c40264fSZachary Turner 
676085328eeSLawrence D'Anna class PythonException : public llvm::ErrorInfo<PythonException> {
677085328eeSLawrence D'Anna private:
678085328eeSLawrence D'Anna   PyObject *m_exception_type, *m_exception, *m_traceback;
679085328eeSLawrence D'Anna   PyObject *m_repr_bytes;
680085328eeSLawrence D'Anna 
681085328eeSLawrence D'Anna public:
682085328eeSLawrence D'Anna   static char ID;
683085328eeSLawrence D'Anna   const char *toCString() const;
684085328eeSLawrence D'Anna   PythonException(const char *caller = nullptr);
685085328eeSLawrence D'Anna   void Restore();
686085328eeSLawrence D'Anna   ~PythonException();
687085328eeSLawrence D'Anna   void log(llvm::raw_ostream &OS) const override;
688085328eeSLawrence D'Anna   std::error_code convertToErrorCode() const override;
689*04edd189SLawrence D'Anna   bool Matches(PyObject *exc) const;
690*04edd189SLawrence D'Anna   std::string ReadBacktrace() const;
691085328eeSLawrence D'Anna };
692085328eeSLawrence D'Anna 
693085328eeSLawrence D'Anna // This extracts the underlying T out of an Expected<T> and returns it.
694085328eeSLawrence D'Anna // If the Expected is an Error instead of a T, that error will be converted
695085328eeSLawrence D'Anna // into a python exception, and this will return a default-constructed T.
696085328eeSLawrence D'Anna //
697085328eeSLawrence D'Anna // This is appropriate for use right at the boundary of python calling into
698085328eeSLawrence D'Anna // C++, such as in a SWIG typemap.   In such a context you should simply
699085328eeSLawrence D'Anna // check if the returned T is valid, and if it is, return a NULL back
700085328eeSLawrence D'Anna // to python.   This will result in the Error being raised as an exception
701085328eeSLawrence D'Anna // from python code's point of view.
702085328eeSLawrence D'Anna //
703085328eeSLawrence D'Anna // For example:
704085328eeSLawrence D'Anna // ```
705085328eeSLawrence D'Anna // Expected<Foo *> efoop = some_cpp_function();
706085328eeSLawrence D'Anna // Foo *foop = unwrapOrSetPythonException(efoop);
707085328eeSLawrence D'Anna // if (!foop)
708085328eeSLawrence D'Anna //    return NULL;
709085328eeSLawrence D'Anna // do_something(*foop);
710085328eeSLawrence D'Anna //
711085328eeSLawrence D'Anna // If the Error returned was itself created because a python exception was
712085328eeSLawrence D'Anna // raised when C++ code called into python, then the original exception
713085328eeSLawrence D'Anna // will be restored.   Otherwise a simple string exception will be raised.
714085328eeSLawrence D'Anna template <typename T> T unwrapOrSetPythonException(llvm::Expected<T> expected) {
715085328eeSLawrence D'Anna   if (expected)
716085328eeSLawrence D'Anna     return expected.get();
717085328eeSLawrence D'Anna   llvm::handleAllErrors(
718085328eeSLawrence D'Anna       expected.takeError(), [](PythonException &E) { E.Restore(); },
719085328eeSLawrence D'Anna       [](const llvm::ErrorInfoBase &E) {
720085328eeSLawrence D'Anna         PyErr_SetString(PyExc_Exception, E.message().c_str());
721085328eeSLawrence D'Anna       });
722085328eeSLawrence D'Anna   return T();
723085328eeSLawrence D'Anna }
724085328eeSLawrence D'Anna 
725722b6189SLawrence D'Anna // This is only here to help incrementally migrate old, exception-unsafe
726722b6189SLawrence D'Anna // code.
727722b6189SLawrence D'Anna template <typename T> T unwrapIgnoringErrors(llvm::Expected<T> expected) {
728722b6189SLawrence D'Anna   if (expected)
729722b6189SLawrence D'Anna     return std::move(expected.get());
730722b6189SLawrence D'Anna   llvm::consumeError(expected.takeError());
731722b6189SLawrence D'Anna   return T();
732722b6189SLawrence D'Anna }
733722b6189SLawrence D'Anna 
734*04edd189SLawrence D'Anna llvm::Expected<PythonObject> runStringOneLine(const llvm::Twine &string,
735*04edd189SLawrence D'Anna                                               const PythonDictionary &globals,
736*04edd189SLawrence D'Anna                                               const PythonDictionary &locals);
737*04edd189SLawrence D'Anna 
738*04edd189SLawrence D'Anna llvm::Expected<PythonObject> runStringMultiLine(const llvm::Twine &string,
739*04edd189SLawrence D'Anna                                                 const PythonDictionary &globals,
740*04edd189SLawrence D'Anna                                                 const PythonDictionary &locals);
741*04edd189SLawrence D'Anna 
742*04edd189SLawrence D'Anna // Sometimes the best way to interact with a python interpreter is
743*04edd189SLawrence D'Anna // to run some python code.   You construct a PythonScript with
744*04edd189SLawrence D'Anna // script string.   The script assigns some function to `_function_`
745*04edd189SLawrence D'Anna // and you get a C++ callable object that calls the python function.
746*04edd189SLawrence D'Anna //
747*04edd189SLawrence D'Anna // Example:
748*04edd189SLawrence D'Anna //
749*04edd189SLawrence D'Anna // const char script[] = R"(
750*04edd189SLawrence D'Anna // def main(x, y):
751*04edd189SLawrence D'Anna //    ....
752*04edd189SLawrence D'Anna // )";
753*04edd189SLawrence D'Anna //
754*04edd189SLawrence D'Anna // Expected<PythonObject> cpp_foo_wrapper(PythonObject x, PythonObject y) {
755*04edd189SLawrence D'Anna //   // no need to synchronize access to this global, we already have the GIL
756*04edd189SLawrence D'Anna //   static PythonScript foo(script)
757*04edd189SLawrence D'Anna //   return  foo(x, y);
758*04edd189SLawrence D'Anna // }
759*04edd189SLawrence D'Anna class PythonScript {
760*04edd189SLawrence D'Anna   const char *script;
761*04edd189SLawrence D'Anna   PythonCallable function;
762*04edd189SLawrence D'Anna 
763*04edd189SLawrence D'Anna   llvm::Error Init();
764*04edd189SLawrence D'Anna 
765*04edd189SLawrence D'Anna public:
766*04edd189SLawrence D'Anna   PythonScript(const char *script) : script(script), function() {}
767*04edd189SLawrence D'Anna 
768*04edd189SLawrence D'Anna   template <typename... Args>
769*04edd189SLawrence D'Anna   llvm::Expected<PythonObject> operator()(Args &&... args) {
770*04edd189SLawrence D'Anna     if (llvm::Error error = Init())
771*04edd189SLawrence D'Anna       return std::move(error);
772*04edd189SLawrence D'Anna     return function.Call(std::forward<Args>(args)...);
773*04edd189SLawrence D'Anna   }
774*04edd189SLawrence D'Anna };
775*04edd189SLawrence D'Anna 
776*04edd189SLawrence D'Anna } // namespace python
7772c1f46dcSZachary Turner } // namespace lldb_private
7782c1f46dcSZachary Turner 
779a281b42bSZachary Turner #endif
780d68983e3SPavel Labath 
781d68983e3SPavel Labath #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
782