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 //
28*d3bd5b3dSLawrence D'Anna //
29*d3bd5b3dSLawrence D'Anna // TODOs for this file
30*d3bd5b3dSLawrence D'Anna //
31*d3bd5b3dSLawrence D'Anna // * Make all methods safe for exceptions.
32*d3bd5b3dSLawrence D'Anna //
33*d3bd5b3dSLawrence D'Anna // * Eliminate method signatures that must translate exceptions into
34*d3bd5b3dSLawrence D'Anna //   empty objects or NULLs.   Almost everything here should return
35*d3bd5b3dSLawrence D'Anna //   Expected<>.   It should be acceptable for certain operations that
36*d3bd5b3dSLawrence D'Anna //   can never fail to assert instead, such as the creation of
37*d3bd5b3dSLawrence D'Anna //   PythonString from a string literal.
38*d3bd5b3dSLawrence D'Anna //
39*d3bd5b3dSLawrence D'Anna // * Elimintate Reset(), and make all non-default constructors private.
40*d3bd5b3dSLawrence D'Anna //   Python objects should be created with Retain<> or Take<>, and they
41*d3bd5b3dSLawrence D'Anna //   should be assigned with operator=
42*d3bd5b3dSLawrence D'Anna //
43*d3bd5b3dSLawrence D'Anna // * Eliminate default constructors, make python objects always
44*d3bd5b3dSLawrence D'Anna //   nonnull, and use optionals where necessary.
45*d3bd5b3dSLawrence D'Anna //
46*d3bd5b3dSLawrence 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 {
62edb35d95SEugene Zelenko 
63085328eeSLawrence D'Anna class PythonObject;
645a72c02bSZachary Turner class PythonBytes;
652c1f46dcSZachary Turner class PythonString;
662c1f46dcSZachary Turner class PythonList;
672c1f46dcSZachary Turner class PythonDictionary;
682c1f46dcSZachary Turner class PythonInteger;
69085328eeSLawrence D'Anna class PythonException;
702c1f46dcSZachary Turner 
71b9c1b51eSKate Stone class StructuredPythonObject : public StructuredData::Generic {
722c1f46dcSZachary Turner public:
73b9c1b51eSKate Stone   StructuredPythonObject() : StructuredData::Generic() {}
742c1f46dcSZachary Turner 
75b9c1b51eSKate Stone   StructuredPythonObject(void *obj) : StructuredData::Generic(obj) {
762c1f46dcSZachary Turner     Py_XINCREF(GetValue());
772c1f46dcSZachary Turner   }
782c1f46dcSZachary Turner 
79b9c1b51eSKate Stone   ~StructuredPythonObject() override {
802c1f46dcSZachary Turner     if (Py_IsInitialized())
812c1f46dcSZachary Turner       Py_XDECREF(GetValue());
822c1f46dcSZachary Turner     SetValue(nullptr);
832c1f46dcSZachary Turner   }
842c1f46dcSZachary Turner 
85b9c1b51eSKate Stone   bool IsValid() const override { return GetValue() && GetValue() != Py_None; }
862c1f46dcSZachary Turner 
872783d817SJonas Devlieghere   void Serialize(llvm::json::OStream &s) const override;
882c1f46dcSZachary Turner 
892c1f46dcSZachary Turner private:
902c1f46dcSZachary Turner   DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject);
912c1f46dcSZachary Turner };
922c1f46dcSZachary Turner 
93b9c1b51eSKate Stone enum class PyObjectType {
942c1f46dcSZachary Turner   Unknown,
952c1f46dcSZachary Turner   None,
96b81d715cSTatyana Krasnukha   Boolean,
972c1f46dcSZachary Turner   Integer,
982c1f46dcSZachary Turner   Dictionary,
992c1f46dcSZachary Turner   List,
1009c40264fSZachary Turner   String,
1015a72c02bSZachary Turner   Bytes,
102f9d6d204SZachary Turner   ByteArray,
1037841efbbSZachary Turner   Module,
104a1405147SZachary Turner   Callable,
105a1405147SZachary Turner   Tuple,
1069c40264fSZachary Turner   File
1072c1f46dcSZachary Turner };
1082c1f46dcSZachary Turner 
109b9c1b51eSKate Stone enum class PyRefType {
110f8b22f8fSZachary Turner   Borrowed, // We are not given ownership of the incoming PyObject.
111f8b22f8fSZachary Turner             // We cannot safely hold it without calling Py_INCREF.
112f8b22f8fSZachary Turner   Owned     // We have ownership of the incoming PyObject.  We should
113f8b22f8fSZachary Turner             // not call Py_INCREF.
114f8b22f8fSZachary Turner };
115f8b22f8fSZachary Turner 
116085328eeSLawrence D'Anna namespace python {
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 
154085328eeSLawrence D'Anna } // namespace python
155085328eeSLawrence D'Anna 
156b9c1b51eSKate Stone enum class PyInitialValue { Invalid, Empty };
157f8b22f8fSZachary Turner 
158085328eeSLawrence D'Anna template <typename T, typename Enable = void> struct PythonFormat;
159085328eeSLawrence D'Anna 
160085328eeSLawrence D'Anna template <> struct PythonFormat<unsigned long long> {
161085328eeSLawrence D'Anna   static constexpr char format = 'K';
162085328eeSLawrence D'Anna   static auto get(unsigned long long value) { return value; }
163085328eeSLawrence D'Anna };
164085328eeSLawrence D'Anna 
165085328eeSLawrence D'Anna template <> struct PythonFormat<long long> {
166085328eeSLawrence D'Anna   static constexpr char format = 'L';
167085328eeSLawrence D'Anna   static auto get(long long value) { return value; }
168085328eeSLawrence D'Anna };
169085328eeSLawrence D'Anna 
170085328eeSLawrence D'Anna template <typename T>
171085328eeSLawrence D'Anna struct PythonFormat<
172085328eeSLawrence D'Anna     T, typename std::enable_if<std::is_base_of<PythonObject, T>::value>::type> {
173085328eeSLawrence D'Anna   static constexpr char format = 'O';
174085328eeSLawrence D'Anna   static auto get(const T &value) { return value.get(); }
175085328eeSLawrence D'Anna };
176085328eeSLawrence D'Anna 
177b9c1b51eSKate Stone class PythonObject {
1782c1f46dcSZachary Turner public:
179b9c1b51eSKate Stone   PythonObject() : m_py_obj(nullptr) {}
1802c1f46dcSZachary Turner 
181b9c1b51eSKate Stone   PythonObject(PyRefType type, PyObject *py_obj) : m_py_obj(nullptr) {
182f8b22f8fSZachary Turner     Reset(type, py_obj);
1832c1f46dcSZachary Turner   }
1842c1f46dcSZachary Turner 
185b9c1b51eSKate Stone   PythonObject(const PythonObject &rhs) : m_py_obj(nullptr) { Reset(rhs); }
1862c1f46dcSZachary Turner 
187085328eeSLawrence D'Anna   PythonObject(PythonObject &&rhs) {
188085328eeSLawrence D'Anna     m_py_obj = rhs.m_py_obj;
189085328eeSLawrence D'Anna     rhs.m_py_obj = nullptr;
190085328eeSLawrence D'Anna   }
191085328eeSLawrence D'Anna 
192*d3bd5b3dSLawrence D'Anna   ~PythonObject() { Reset(); }
1932c1f46dcSZachary Turner 
194b9c1b51eSKate Stone   void Reset() {
195085328eeSLawrence D'Anna     if (m_py_obj && Py_IsInitialized())
196085328eeSLawrence D'Anna       Py_DECREF(m_py_obj);
197f8b22f8fSZachary Turner     m_py_obj = nullptr;
1982c1f46dcSZachary Turner   }
199f8b22f8fSZachary Turner 
200b9c1b51eSKate Stone   void Reset(const PythonObject &rhs) {
20160c24f70SZachary Turner     if (!rhs.IsValid())
202f8b22f8fSZachary Turner       Reset();
203f8b22f8fSZachary Turner     else
204f8b22f8fSZachary Turner       Reset(PyRefType::Borrowed, rhs.m_py_obj);
205f8b22f8fSZachary Turner   }
206f8b22f8fSZachary Turner 
207f8b22f8fSZachary Turner   // PythonObject is implicitly convertible to PyObject *, which will call the
208f8b22f8fSZachary Turner   // wrong overload.  We want to explicitly disallow this, since a PyObject
209f8b22f8fSZachary Turner   // *always* owns its reference.  Therefore the overload which takes a
210f8b22f8fSZachary Turner   // PyRefType doesn't make sense, and the copy constructor should be used.
211b9c1b51eSKate Stone   void Reset(PyRefType type, const PythonObject &ref) = delete;
212f8b22f8fSZachary Turner 
213*d3bd5b3dSLawrence D'Anna   void Reset(PyRefType type, PyObject *py_obj) {
214f8b22f8fSZachary Turner     if (py_obj == m_py_obj)
215f8b22f8fSZachary Turner       return;
216f8b22f8fSZachary Turner 
217f8b22f8fSZachary Turner     if (Py_IsInitialized())
218f8b22f8fSZachary Turner       Py_XDECREF(m_py_obj);
219f8b22f8fSZachary Turner 
220f8b22f8fSZachary Turner     m_py_obj = py_obj;
221f8b22f8fSZachary Turner 
222f8b22f8fSZachary Turner     // If this is a borrowed reference, we need to convert it to
223f8b22f8fSZachary Turner     // an owned reference by incrementing it.  If it is an owned
224f8b22f8fSZachary Turner     // reference (for example the caller allocated it with PyDict_New()
225f8b22f8fSZachary Turner     // then we must *not* increment it.
226085328eeSLawrence D'Anna     if (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed)
227f8b22f8fSZachary Turner       Py_XINCREF(m_py_obj);
2282c1f46dcSZachary Turner   }
2292c1f46dcSZachary Turner 
230b9c1b51eSKate Stone   void Dump() const {
2312c1f46dcSZachary Turner     if (m_py_obj)
2322c1f46dcSZachary Turner       _PyObject_Dump(m_py_obj);
2332c1f46dcSZachary Turner     else
2342c1f46dcSZachary Turner       puts("NULL");
2352c1f46dcSZachary Turner   }
2362c1f46dcSZachary Turner 
237b9c1b51eSKate Stone   void Dump(Stream &strm) const;
2382c1f46dcSZachary Turner 
239b9c1b51eSKate Stone   PyObject *get() const { return m_py_obj; }
2402c1f46dcSZachary Turner 
241b9c1b51eSKate Stone   PyObject *release() {
24260c24f70SZachary Turner     PyObject *result = m_py_obj;
24360c24f70SZachary Turner     m_py_obj = nullptr;
24460c24f70SZachary Turner     return result;
24560c24f70SZachary Turner   }
24660c24f70SZachary Turner 
247b9c1b51eSKate Stone   PythonObject &operator=(const PythonObject &other) {
248f8b22f8fSZachary Turner     Reset(PyRefType::Borrowed, other.get());
249f8b22f8fSZachary Turner     return *this;
2502c1f46dcSZachary Turner   }
2512c1f46dcSZachary Turner 
252085328eeSLawrence D'Anna   void Reset(PythonObject &&other) {
253085328eeSLawrence D'Anna     Reset();
254085328eeSLawrence D'Anna     m_py_obj = other.m_py_obj;
255085328eeSLawrence D'Anna     other.m_py_obj = nullptr;
256085328eeSLawrence D'Anna   }
257085328eeSLawrence D'Anna 
258085328eeSLawrence D'Anna   PythonObject &operator=(PythonObject &&other) {
259085328eeSLawrence D'Anna     Reset(std::move(other));
260085328eeSLawrence D'Anna     return *this;
261085328eeSLawrence D'Anna   }
262085328eeSLawrence D'Anna 
263b9c1b51eSKate Stone   PyObjectType GetObjectType() const;
2647841efbbSZachary Turner 
265b9c1b51eSKate Stone   PythonString Repr() const;
2667841efbbSZachary Turner 
267b9c1b51eSKate Stone   PythonString Str() const;
2687841efbbSZachary Turner 
269b9c1b51eSKate Stone   static PythonObject ResolveNameWithDictionary(llvm::StringRef name,
270b9c1b51eSKate Stone                                                 const PythonDictionary &dict);
2717841efbbSZachary Turner 
272b58fb2f4SZachary Turner   template <typename T>
273b9c1b51eSKate Stone   static T ResolveNameWithDictionary(llvm::StringRef name,
274b9c1b51eSKate Stone                                      const PythonDictionary &dict) {
275b58fb2f4SZachary Turner     return ResolveNameWithDictionary(name, dict).AsType<T>();
276b58fb2f4SZachary Turner   }
277b58fb2f4SZachary Turner 
278b9c1b51eSKate Stone   PythonObject ResolveName(llvm::StringRef name) const;
2797841efbbSZachary Turner 
280b9c1b51eSKate Stone   template <typename T> T ResolveName(llvm::StringRef name) const {
281b58fb2f4SZachary Turner     return ResolveName(name).AsType<T>();
282b58fb2f4SZachary Turner   }
283b58fb2f4SZachary Turner 
284b9c1b51eSKate Stone   bool HasAttribute(llvm::StringRef attribute) const;
2859c40264fSZachary Turner 
286b9c1b51eSKate Stone   PythonObject GetAttributeValue(llvm::StringRef attribute) const;
2877d6d218eSZachary Turner 
288085328eeSLawrence D'Anna   bool IsNone() const { return m_py_obj == Py_None; }
289f8b22f8fSZachary Turner 
290085328eeSLawrence D'Anna   bool IsValid() const { return m_py_obj != nullptr; }
291f8b22f8fSZachary Turner 
292085328eeSLawrence D'Anna   bool IsAllocated() const { return IsValid() && !IsNone(); }
293085328eeSLawrence D'Anna 
294085328eeSLawrence D'Anna   explicit operator bool() const { return IsValid() && !IsNone(); }
2952c1f46dcSZachary Turner 
296b9c1b51eSKate Stone   template <typename T> T AsType() const {
2977d6d218eSZachary Turner     if (!T::Check(m_py_obj))
2987d6d218eSZachary Turner       return T();
2997d6d218eSZachary Turner     return T(PyRefType::Borrowed, m_py_obj);
3007d6d218eSZachary Turner   }
3017d6d218eSZachary Turner 
302b9c1b51eSKate Stone   StructuredData::ObjectSP CreateStructuredObject() const;
3032c1f46dcSZachary Turner 
3042c1f46dcSZachary Turner protected:
305085328eeSLawrence D'Anna   static llvm::Error nullDeref() {
306085328eeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
307085328eeSLawrence D'Anna                                    "A NULL PyObject* was dereferenced");
308085328eeSLawrence D'Anna   }
309085328eeSLawrence D'Anna   static llvm::Error exception(const char *s = nullptr) {
310085328eeSLawrence D'Anna     return llvm::make_error<PythonException>(s);
311085328eeSLawrence D'Anna   }
312085328eeSLawrence D'Anna 
313085328eeSLawrence D'Anna public:
314085328eeSLawrence D'Anna   template <typename... T>
315085328eeSLawrence D'Anna   llvm::Expected<PythonObject> CallMethod(const char *name,
316085328eeSLawrence D'Anna                                           const T &... t) const {
317085328eeSLawrence D'Anna     const char format[] = {'(', PythonFormat<T>::format..., ')', 0};
318085328eeSLawrence D'Anna #if PY_MAJOR_VERSION < 3
319085328eeSLawrence D'Anna     PyObject *obj = PyObject_CallMethod(m_py_obj, const_cast<char *>(name),
320085328eeSLawrence D'Anna                                         const_cast<char *>(format),
321085328eeSLawrence D'Anna                                         PythonFormat<T>::get(t)...);
322085328eeSLawrence D'Anna #else
323085328eeSLawrence D'Anna     PyObject *obj =
324085328eeSLawrence D'Anna         PyObject_CallMethod(m_py_obj, name, format, PythonFormat<T>::get(t)...);
325085328eeSLawrence D'Anna #endif
326085328eeSLawrence D'Anna     if (!obj)
327085328eeSLawrence D'Anna       return exception();
328085328eeSLawrence D'Anna     return python::Take<PythonObject>(obj);
329085328eeSLawrence D'Anna   }
330085328eeSLawrence D'Anna 
331085328eeSLawrence D'Anna   llvm::Expected<PythonObject> GetAttribute(const char *name) const {
332085328eeSLawrence D'Anna     if (!m_py_obj)
333085328eeSLawrence D'Anna       return nullDeref();
334085328eeSLawrence D'Anna     PyObject *obj = PyObject_GetAttrString(m_py_obj, name);
335085328eeSLawrence D'Anna     if (!obj)
336085328eeSLawrence D'Anna       return exception();
337085328eeSLawrence D'Anna     return python::Take<PythonObject>(obj);
338085328eeSLawrence D'Anna   }
339085328eeSLawrence D'Anna 
340085328eeSLawrence D'Anna   llvm::Expected<bool> IsTrue() {
341085328eeSLawrence D'Anna     if (!m_py_obj)
342085328eeSLawrence D'Anna       return nullDeref();
343085328eeSLawrence D'Anna     int r = PyObject_IsTrue(m_py_obj);
344085328eeSLawrence D'Anna     if (r < 0)
345085328eeSLawrence D'Anna       return exception();
346085328eeSLawrence D'Anna     return !!r;
347085328eeSLawrence D'Anna   }
348085328eeSLawrence D'Anna 
349085328eeSLawrence D'Anna   llvm::Expected<long long> AsLongLong() {
350085328eeSLawrence D'Anna     if (!m_py_obj)
351085328eeSLawrence D'Anna       return nullDeref();
352085328eeSLawrence D'Anna     assert(!PyErr_Occurred());
353085328eeSLawrence D'Anna     long long r = PyLong_AsLongLong(m_py_obj);
354085328eeSLawrence D'Anna     if (PyErr_Occurred())
355085328eeSLawrence D'Anna       return exception();
356085328eeSLawrence D'Anna     return r;
357085328eeSLawrence D'Anna   }
358085328eeSLawrence D'Anna 
359085328eeSLawrence D'Anna   llvm::Expected<bool> IsInstance(const PythonObject &cls) {
360085328eeSLawrence D'Anna     if (!m_py_obj || !cls.IsValid())
361085328eeSLawrence D'Anna       return nullDeref();
362085328eeSLawrence D'Anna     int r = PyObject_IsInstance(m_py_obj, cls.get());
363085328eeSLawrence D'Anna     if (r < 0)
364085328eeSLawrence D'Anna       return exception();
365085328eeSLawrence D'Anna     return !!r;
366085328eeSLawrence D'Anna   }
367085328eeSLawrence D'Anna 
368085328eeSLawrence D'Anna protected:
3692c1f46dcSZachary Turner   PyObject *m_py_obj;
3702c1f46dcSZachary Turner };
3712c1f46dcSZachary Turner 
372085328eeSLawrence D'Anna namespace python {
373085328eeSLawrence D'Anna 
374085328eeSLawrence D'Anna // This is why C++ needs monads.
375085328eeSLawrence D'Anna template <typename T> llvm::Expected<T> As(llvm::Expected<PythonObject> &&obj) {
376085328eeSLawrence D'Anna   if (!obj)
377085328eeSLawrence D'Anna     return obj.takeError();
378085328eeSLawrence D'Anna   if (!T::Check(obj.get().get()))
379085328eeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
380085328eeSLawrence D'Anna                                    "type error");
381085328eeSLawrence D'Anna   return T(PyRefType::Borrowed, std::move(obj.get().get()));
382085328eeSLawrence D'Anna }
383085328eeSLawrence D'Anna 
384085328eeSLawrence D'Anna template <> llvm::Expected<bool> As<bool>(llvm::Expected<PythonObject> &&obj);
385085328eeSLawrence D'Anna 
386085328eeSLawrence D'Anna template <>
387085328eeSLawrence D'Anna llvm::Expected<long long> As<long long>(llvm::Expected<PythonObject> &&obj);
388085328eeSLawrence D'Anna 
389085328eeSLawrence D'Anna } // namespace python
390085328eeSLawrence D'Anna 
391*d3bd5b3dSLawrence D'Anna template <class T> class TypedPythonObject : public PythonObject {
3925a72c02bSZachary Turner public:
393*d3bd5b3dSLawrence D'Anna   // override to perform implicit type conversions on Reset
394*d3bd5b3dSLawrence D'Anna   // This can be eliminated once we drop python 2 support.
395*d3bd5b3dSLawrence D'Anna   static void Convert(PyRefType &type, PyObject *&py_obj) {}
396*d3bd5b3dSLawrence D'Anna 
397*d3bd5b3dSLawrence D'Anna   using PythonObject::Reset;
398*d3bd5b3dSLawrence D'Anna 
399*d3bd5b3dSLawrence D'Anna   void Reset(PyRefType type, PyObject *py_obj) {
400*d3bd5b3dSLawrence D'Anna     Reset();
401*d3bd5b3dSLawrence D'Anna     if (!py_obj)
402*d3bd5b3dSLawrence D'Anna       return;
403*d3bd5b3dSLawrence D'Anna     T::Convert(type, py_obj);
404*d3bd5b3dSLawrence D'Anna     if (T::Check(py_obj))
405*d3bd5b3dSLawrence D'Anna       PythonObject::Reset(type, py_obj);
406*d3bd5b3dSLawrence D'Anna     else if (type == PyRefType::Owned)
407*d3bd5b3dSLawrence D'Anna       Py_DECREF(py_obj);
408*d3bd5b3dSLawrence D'Anna   }
409*d3bd5b3dSLawrence D'Anna 
410*d3bd5b3dSLawrence D'Anna   TypedPythonObject(PyRefType type, PyObject *py_obj) { Reset(type, py_obj); }
411*d3bd5b3dSLawrence D'Anna 
412*d3bd5b3dSLawrence D'Anna   TypedPythonObject() {}
413*d3bd5b3dSLawrence D'Anna };
414*d3bd5b3dSLawrence D'Anna 
415*d3bd5b3dSLawrence D'Anna class PythonBytes : public TypedPythonObject<PythonBytes> {
416*d3bd5b3dSLawrence D'Anna public:
417*d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
4185a72c02bSZachary Turner   explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes);
4195a72c02bSZachary Turner   PythonBytes(const uint8_t *bytes, size_t length);
4205a72c02bSZachary Turner 
421b9c1b51eSKate Stone   static bool Check(PyObject *py_obj);
4225a72c02bSZachary Turner 
423b9c1b51eSKate Stone   llvm::ArrayRef<uint8_t> GetBytes() const;
4245a72c02bSZachary Turner 
425b9c1b51eSKate Stone   size_t GetSize() const;
4265a72c02bSZachary Turner 
427b9c1b51eSKate Stone   void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
4285a72c02bSZachary Turner 
429b9c1b51eSKate Stone   StructuredData::StringSP CreateStructuredString() const;
4305a72c02bSZachary Turner };
4315a72c02bSZachary Turner 
432*d3bd5b3dSLawrence D'Anna class PythonByteArray : public TypedPythonObject<PythonByteArray> {
433f9d6d204SZachary Turner public:
434*d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
435f9d6d204SZachary Turner   explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes);
436f9d6d204SZachary Turner   PythonByteArray(const uint8_t *bytes, size_t length);
437f9d6d204SZachary Turner   PythonByteArray(const PythonBytes &object);
438f9d6d204SZachary Turner 
439b9c1b51eSKate Stone   static bool Check(PyObject *py_obj);
440f9d6d204SZachary Turner 
441b9c1b51eSKate Stone   llvm::ArrayRef<uint8_t> GetBytes() const;
442f9d6d204SZachary Turner 
443b9c1b51eSKate Stone   size_t GetSize() const;
444f9d6d204SZachary Turner 
445b9c1b51eSKate Stone   void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
446f9d6d204SZachary Turner 
447b9c1b51eSKate Stone   StructuredData::StringSP CreateStructuredString() const;
448f9d6d204SZachary Turner };
449f9d6d204SZachary Turner 
450*d3bd5b3dSLawrence D'Anna class PythonString : public TypedPythonObject<PythonString> {
4512c1f46dcSZachary Turner public:
452*d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
453085328eeSLawrence D'Anna   static llvm::Expected<PythonString> FromUTF8(llvm::StringRef string);
454085328eeSLawrence D'Anna 
455*d3bd5b3dSLawrence D'Anna   PythonString() : TypedPythonObject() {} // MSVC requires this for some reason
456edb35d95SEugene Zelenko 
457*d3bd5b3dSLawrence D'Anna   explicit PythonString(llvm::StringRef string); // safe, null on error
4582c1f46dcSZachary Turner 
45922c8efcdSZachary Turner   static bool Check(PyObject *py_obj);
460*d3bd5b3dSLawrence D'Anna   static void Convert(PyRefType &type, PyObject *&py_obj);
4612c1f46dcSZachary Turner 
462085328eeSLawrence D'Anna   llvm::StringRef GetString() const; // safe, empty string on error
463085328eeSLawrence D'Anna 
464085328eeSLawrence D'Anna   llvm::Expected<llvm::StringRef> AsUTF8() const;
4652c1f46dcSZachary Turner 
466b9c1b51eSKate Stone   size_t GetSize() const;
4672c1f46dcSZachary Turner 
468085328eeSLawrence D'Anna   void SetString(llvm::StringRef string); // safe, null on error
4692c1f46dcSZachary Turner 
4702c1f46dcSZachary Turner   StructuredData::StringSP CreateStructuredString() const;
4712c1f46dcSZachary Turner };
4722c1f46dcSZachary Turner 
473*d3bd5b3dSLawrence D'Anna class PythonInteger : public TypedPythonObject<PythonInteger> {
4742c1f46dcSZachary Turner public:
475*d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
476edb35d95SEugene Zelenko 
477*d3bd5b3dSLawrence D'Anna   PythonInteger() : TypedPythonObject() {} // MSVC requires this for some reason
478*d3bd5b3dSLawrence D'Anna 
479*d3bd5b3dSLawrence D'Anna   explicit PythonInteger(int64_t value);
4802c1f46dcSZachary Turner 
48122c8efcdSZachary Turner   static bool Check(PyObject *py_obj);
482*d3bd5b3dSLawrence D'Anna   static void Convert(PyRefType &type, PyObject *&py_obj);
4832c1f46dcSZachary Turner 
4842c1f46dcSZachary Turner   int64_t GetInteger() const;
4852c1f46dcSZachary Turner 
486b9c1b51eSKate Stone   void SetInteger(int64_t value);
4872c1f46dcSZachary Turner 
4882c1f46dcSZachary Turner   StructuredData::IntegerSP CreateStructuredInteger() const;
4892c1f46dcSZachary Turner };
4902c1f46dcSZachary Turner 
491*d3bd5b3dSLawrence D'Anna class PythonBoolean : public TypedPythonObject<PythonBoolean> {
492b81d715cSTatyana Krasnukha public:
493*d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
494b81d715cSTatyana Krasnukha 
495*d3bd5b3dSLawrence D'Anna   explicit PythonBoolean(bool value);
496b81d715cSTatyana Krasnukha 
497b81d715cSTatyana Krasnukha   static bool Check(PyObject *py_obj);
498b81d715cSTatyana Krasnukha 
499b81d715cSTatyana Krasnukha   bool GetValue() const;
500b81d715cSTatyana Krasnukha 
501b81d715cSTatyana Krasnukha   void SetValue(bool value);
502b81d715cSTatyana Krasnukha 
503b81d715cSTatyana Krasnukha   StructuredData::BooleanSP CreateStructuredBoolean() const;
504b81d715cSTatyana Krasnukha };
505b81d715cSTatyana Krasnukha 
506*d3bd5b3dSLawrence D'Anna class PythonList : public TypedPythonObject<PythonList> {
5072c1f46dcSZachary Turner public:
508*d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
509*d3bd5b3dSLawrence D'Anna 
510*d3bd5b3dSLawrence D'Anna   PythonList() : TypedPythonObject() {} // MSVC requires this for some reason
511*d3bd5b3dSLawrence D'Anna 
51287f47729SZachary Turner   explicit PythonList(PyInitialValue value);
51387f47729SZachary Turner   explicit PythonList(int list_size);
5142c1f46dcSZachary Turner 
51522c8efcdSZachary Turner   static bool Check(PyObject *py_obj);
51622c8efcdSZachary Turner 
5172c1f46dcSZachary Turner   uint32_t GetSize() const;
5182c1f46dcSZachary Turner 
5192c1f46dcSZachary Turner   PythonObject GetItemAtIndex(uint32_t index) const;
5202c1f46dcSZachary Turner 
521f8b22f8fSZachary Turner   void SetItemAtIndex(uint32_t index, const PythonObject &object);
5222c1f46dcSZachary Turner 
523f8b22f8fSZachary Turner   void AppendItem(const PythonObject &object);
5242c1f46dcSZachary Turner 
5252c1f46dcSZachary Turner   StructuredData::ArraySP CreateStructuredArray() const;
5262c1f46dcSZachary Turner };
5272c1f46dcSZachary Turner 
528*d3bd5b3dSLawrence D'Anna class PythonTuple : public TypedPythonObject<PythonTuple> {
529a1405147SZachary Turner public:
530*d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
531*d3bd5b3dSLawrence D'Anna 
532a1405147SZachary Turner   explicit PythonTuple(PyInitialValue value);
533a1405147SZachary Turner   explicit PythonTuple(int tuple_size);
534a1405147SZachary Turner   PythonTuple(std::initializer_list<PythonObject> objects);
535a1405147SZachary Turner   PythonTuple(std::initializer_list<PyObject *> objects);
536a1405147SZachary Turner 
537a1405147SZachary Turner   static bool Check(PyObject *py_obj);
538a1405147SZachary Turner 
539a1405147SZachary Turner   uint32_t GetSize() const;
540a1405147SZachary Turner 
541a1405147SZachary Turner   PythonObject GetItemAtIndex(uint32_t index) const;
542a1405147SZachary Turner 
543a1405147SZachary Turner   void SetItemAtIndex(uint32_t index, const PythonObject &object);
544a1405147SZachary Turner 
545a1405147SZachary Turner   StructuredData::ArraySP CreateStructuredArray() const;
546a1405147SZachary Turner };
547a1405147SZachary Turner 
548*d3bd5b3dSLawrence D'Anna class PythonDictionary : public TypedPythonObject<PythonDictionary> {
5492c1f46dcSZachary Turner public:
550*d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
551edb35d95SEugene Zelenko 
552*d3bd5b3dSLawrence D'Anna   PythonDictionary() : TypedPythonObject() {} // MSVC requires this for some reason
553*d3bd5b3dSLawrence D'Anna 
554*d3bd5b3dSLawrence D'Anna   explicit PythonDictionary(PyInitialValue value);
5552c1f46dcSZachary Turner 
55622c8efcdSZachary Turner   static bool Check(PyObject *py_obj);
55722c8efcdSZachary Turner 
5582c1f46dcSZachary Turner   uint32_t GetSize() const;
5592c1f46dcSZachary Turner 
560f8b22f8fSZachary Turner   PythonList GetKeys() const;
5612c1f46dcSZachary Turner 
562f8b22f8fSZachary Turner   PythonObject GetItemForKey(const PythonObject &key) const;
563f8b22f8fSZachary Turner   void SetItemForKey(const PythonObject &key, const PythonObject &value);
5642c1f46dcSZachary Turner 
5652c1f46dcSZachary Turner   StructuredData::DictionarySP CreateStructuredDictionary() const;
5662c1f46dcSZachary Turner };
56787f47729SZachary Turner 
568*d3bd5b3dSLawrence D'Anna class PythonModule : public TypedPythonObject<PythonModule> {
5697841efbbSZachary Turner public:
570*d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
5717841efbbSZachary Turner 
5727841efbbSZachary Turner   static bool Check(PyObject *py_obj);
5737841efbbSZachary Turner 
574b9c1b51eSKate Stone   static PythonModule BuiltinsModule();
575a1405147SZachary Turner 
576b9c1b51eSKate Stone   static PythonModule MainModule();
577a1405147SZachary Turner 
578b9c1b51eSKate Stone   static PythonModule AddModule(llvm::StringRef module);
5797841efbbSZachary Turner 
580085328eeSLawrence D'Anna   // safe, returns invalid on error;
581085328eeSLawrence D'Anna   static PythonModule ImportModule(llvm::StringRef name) {
582085328eeSLawrence D'Anna     std::string s = name;
583085328eeSLawrence D'Anna     auto mod = Import(s.c_str());
584085328eeSLawrence D'Anna     if (!mod) {
585085328eeSLawrence D'Anna       llvm::consumeError(mod.takeError());
586085328eeSLawrence D'Anna       return PythonModule();
587085328eeSLawrence D'Anna     }
588085328eeSLawrence D'Anna     return std::move(mod.get());
589085328eeSLawrence D'Anna   }
590085328eeSLawrence D'Anna 
591085328eeSLawrence D'Anna   static llvm::Expected<PythonModule> Import(const char *name);
592085328eeSLawrence D'Anna 
593085328eeSLawrence D'Anna   llvm::Expected<PythonObject> Get(const char *name);
5942419f1d5SZachary Turner 
5957841efbbSZachary Turner   PythonDictionary GetDictionary() const;
5967841efbbSZachary Turner };
5977841efbbSZachary Turner 
598*d3bd5b3dSLawrence D'Anna class PythonCallable : public TypedPythonObject<PythonCallable> {
599a1405147SZachary Turner public:
600*d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
601*d3bd5b3dSLawrence D'Anna 
602b58fb2f4SZachary Turner   struct ArgInfo {
603b58fb2f4SZachary Turner     size_t count;
604a5d6765cSEnrico Granata     bool is_bound_method : 1;
605b58fb2f4SZachary Turner     bool has_varargs : 1;
606b58fb2f4SZachary Turner     bool has_kwargs : 1;
607b58fb2f4SZachary Turner   };
608b58fb2f4SZachary Turner 
609b9c1b51eSKate Stone   static bool Check(PyObject *py_obj);
610a1405147SZachary Turner 
611b9c1b51eSKate Stone   ArgInfo GetNumArguments() const;
61227a14f19SJim Ingham 
61327a14f19SJim Ingham   // If the callable is a Py_Class, then find the number of arguments
61427a14f19SJim Ingham   // of the __init__ method.
61527a14f19SJim Ingham   ArgInfo GetNumInitArguments() const;
616b58fb2f4SZachary Turner 
617b9c1b51eSKate Stone   PythonObject operator()();
618a1405147SZachary Turner 
619b9c1b51eSKate Stone   PythonObject operator()(std::initializer_list<PyObject *> args);
620a1405147SZachary Turner 
621b9c1b51eSKate Stone   PythonObject operator()(std::initializer_list<PythonObject> args);
622b58fb2f4SZachary Turner 
623b58fb2f4SZachary Turner   template <typename Arg, typename... Args>
624b9c1b51eSKate Stone   PythonObject operator()(const Arg &arg, Args... args) {
625b58fb2f4SZachary Turner     return operator()({arg, args...});
626b58fb2f4SZachary Turner   }
627a1405147SZachary Turner };
628a1405147SZachary Turner 
629*d3bd5b3dSLawrence D'Anna class PythonFile : public TypedPythonObject<PythonFile> {
6309c40264fSZachary Turner public:
631*d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
632edb35d95SEugene Zelenko 
633*d3bd5b3dSLawrence D'Anna   PythonFile() : TypedPythonObject() {} // MSVC requires this for some reason
6349c40264fSZachary Turner 
6359c40264fSZachary Turner   static bool Check(PyObject *py_obj);
6369c40264fSZachary Turner 
637d9b553ecSLawrence D'Anna   static llvm::Expected<PythonFile> FromFile(File &file,
638d9b553ecSLawrence D'Anna                                              const char *mode = nullptr);
639d9b553ecSLawrence D'Anna 
640d9b553ecSLawrence D'Anna   // FIXME delete this after FILE* typemaps are deleted
641d9b553ecSLawrence D'Anna   // and ScriptInterpreterPython is fixed
642d9b553ecSLawrence D'Anna   PythonFile(File &file, const char *mode = nullptr) {
643d9b553ecSLawrence D'Anna     auto f = FromFile(file, mode);
644d9b553ecSLawrence D'Anna     if (f)
645d9b553ecSLawrence D'Anna       *this = std::move(f.get());
646d9b553ecSLawrence D'Anna     else {
647d9b553ecSLawrence D'Anna       Reset();
648d9b553ecSLawrence D'Anna       llvm::consumeError(f.takeError());
649d9b553ecSLawrence D'Anna     }
650d9b553ecSLawrence D'Anna   }
651eda01c31SZachary Turner 
6522fce1137SLawrence D'Anna   lldb::FileUP GetUnderlyingFile() const;
653085328eeSLawrence D'Anna 
654085328eeSLawrence D'Anna   llvm::Expected<lldb::FileSP> ConvertToFile(bool borrowed = false);
655085328eeSLawrence D'Anna   llvm::Expected<lldb::FileSP>
656085328eeSLawrence D'Anna   ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed = false);
6579c40264fSZachary Turner };
6589c40264fSZachary Turner 
659085328eeSLawrence D'Anna class PythonException : public llvm::ErrorInfo<PythonException> {
660085328eeSLawrence D'Anna private:
661085328eeSLawrence D'Anna   PyObject *m_exception_type, *m_exception, *m_traceback;
662085328eeSLawrence D'Anna   PyObject *m_repr_bytes;
663085328eeSLawrence D'Anna 
664085328eeSLawrence D'Anna public:
665085328eeSLawrence D'Anna   static char ID;
666085328eeSLawrence D'Anna   const char *toCString() const;
667085328eeSLawrence D'Anna   PythonException(const char *caller = nullptr);
668085328eeSLawrence D'Anna   void Restore();
669085328eeSLawrence D'Anna   ~PythonException();
670085328eeSLawrence D'Anna   void log(llvm::raw_ostream &OS) const override;
671085328eeSLawrence D'Anna   std::error_code convertToErrorCode() const override;
672085328eeSLawrence D'Anna };
673085328eeSLawrence D'Anna 
674085328eeSLawrence D'Anna // This extracts the underlying T out of an Expected<T> and returns it.
675085328eeSLawrence D'Anna // If the Expected is an Error instead of a T, that error will be converted
676085328eeSLawrence D'Anna // into a python exception, and this will return a default-constructed T.
677085328eeSLawrence D'Anna //
678085328eeSLawrence D'Anna // This is appropriate for use right at the boundary of python calling into
679085328eeSLawrence D'Anna // C++, such as in a SWIG typemap.   In such a context you should simply
680085328eeSLawrence D'Anna // check if the returned T is valid, and if it is, return a NULL back
681085328eeSLawrence D'Anna // to python.   This will result in the Error being raised as an exception
682085328eeSLawrence D'Anna // from python code's point of view.
683085328eeSLawrence D'Anna //
684085328eeSLawrence D'Anna // For example:
685085328eeSLawrence D'Anna // ```
686085328eeSLawrence D'Anna // Expected<Foo *> efoop = some_cpp_function();
687085328eeSLawrence D'Anna // Foo *foop = unwrapOrSetPythonException(efoop);
688085328eeSLawrence D'Anna // if (!foop)
689085328eeSLawrence D'Anna //    return NULL;
690085328eeSLawrence D'Anna // do_something(*foop);
691085328eeSLawrence D'Anna //
692085328eeSLawrence D'Anna // If the Error returned was itself created because a python exception was
693085328eeSLawrence D'Anna // raised when C++ code called into python, then the original exception
694085328eeSLawrence D'Anna // will be restored.   Otherwise a simple string exception will be raised.
695085328eeSLawrence D'Anna template <typename T> T unwrapOrSetPythonException(llvm::Expected<T> expected) {
696085328eeSLawrence D'Anna   if (expected)
697085328eeSLawrence D'Anna     return expected.get();
698085328eeSLawrence D'Anna   llvm::handleAllErrors(
699085328eeSLawrence D'Anna       expected.takeError(), [](PythonException &E) { E.Restore(); },
700085328eeSLawrence D'Anna       [](const llvm::ErrorInfoBase &E) {
701085328eeSLawrence D'Anna         PyErr_SetString(PyExc_Exception, E.message().c_str());
702085328eeSLawrence D'Anna       });
703085328eeSLawrence D'Anna   return T();
704085328eeSLawrence D'Anna }
705085328eeSLawrence D'Anna 
7062c1f46dcSZachary Turner } // namespace lldb_private
7072c1f46dcSZachary Turner 
708a281b42bSZachary Turner #endif
709d68983e3SPavel Labath 
710d68983e3SPavel Labath #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
711