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 
9*085328eeSLawrence D'Anna //
10*085328eeSLawrence D'Anna // !! FIXME FIXME FIXME !!
11*085328eeSLawrence D'Anna //
12*085328eeSLawrence D'Anna // Python APIs nearly all can return an exception.   They do this
13*085328eeSLawrence D'Anna // by returning NULL, or -1, or some such value and setting
14*085328eeSLawrence D'Anna // the exception state with PyErr_Set*().   Exceptions must be
15*085328eeSLawrence D'Anna // handled before further python API functions are called.   Failure
16*085328eeSLawrence D'Anna // to do so will result in asserts on debug builds of python.
17*085328eeSLawrence D'Anna // It will also sometimes, but not usually result in crashes of
18*085328eeSLawrence D'Anna // release builds.
19*085328eeSLawrence D'Anna //
20*085328eeSLawrence D'Anna // Nearly all the code in this header does not handle python exceptions
21*085328eeSLawrence D'Anna // correctly.  It should all be converted to return Expected<> or
22*085328eeSLawrence D'Anna // Error types to capture the exception.
23*085328eeSLawrence D'Anna //
24*085328eeSLawrence D'Anna // Everything in this file except functions that return Error or
25*085328eeSLawrence D'Anna // Expected<> is considered deprecated and should not be
26*085328eeSLawrence D'Anna // used in new code.  If you need to use it, fix it first.
27*085328eeSLawrence D'Anna //
28*085328eeSLawrence D'Anna 
292c1f46dcSZachary Turner #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
302c1f46dcSZachary Turner #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
312c1f46dcSZachary Turner 
32d68983e3SPavel Labath #ifndef LLDB_DISABLE_PYTHON
33d68983e3SPavel Labath 
3441de9a97SKate Stone // LLDB Python header must be included first
3541de9a97SKate Stone #include "lldb-python.h"
3641de9a97SKate Stone 
379c40264fSZachary Turner #include "lldb/Host/File.h"
38f2a8bccfSPavel Labath #include "lldb/Utility/StructuredData.h"
392c1f46dcSZachary Turner 
405a72c02bSZachary Turner #include "llvm/ADT/ArrayRef.h"
415a72c02bSZachary Turner 
422c1f46dcSZachary Turner namespace lldb_private {
43edb35d95SEugene Zelenko 
44*085328eeSLawrence D'Anna class PythonObject;
455a72c02bSZachary Turner class PythonBytes;
462c1f46dcSZachary Turner class PythonString;
472c1f46dcSZachary Turner class PythonList;
482c1f46dcSZachary Turner class PythonDictionary;
492c1f46dcSZachary Turner class PythonInteger;
50*085328eeSLawrence D'Anna class PythonException;
512c1f46dcSZachary Turner 
52b9c1b51eSKate Stone class StructuredPythonObject : public StructuredData::Generic {
532c1f46dcSZachary Turner public:
54b9c1b51eSKate Stone   StructuredPythonObject() : StructuredData::Generic() {}
552c1f46dcSZachary Turner 
56b9c1b51eSKate Stone   StructuredPythonObject(void *obj) : StructuredData::Generic(obj) {
572c1f46dcSZachary Turner     Py_XINCREF(GetValue());
582c1f46dcSZachary Turner   }
592c1f46dcSZachary Turner 
60b9c1b51eSKate Stone   ~StructuredPythonObject() override {
612c1f46dcSZachary Turner     if (Py_IsInitialized())
622c1f46dcSZachary Turner       Py_XDECREF(GetValue());
632c1f46dcSZachary Turner     SetValue(nullptr);
642c1f46dcSZachary Turner   }
652c1f46dcSZachary Turner 
66b9c1b51eSKate Stone   bool IsValid() const override { return GetValue() && GetValue() != Py_None; }
672c1f46dcSZachary Turner 
682783d817SJonas Devlieghere   void Serialize(llvm::json::OStream &s) const override;
692c1f46dcSZachary Turner 
702c1f46dcSZachary Turner private:
712c1f46dcSZachary Turner   DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject);
722c1f46dcSZachary Turner };
732c1f46dcSZachary Turner 
74b9c1b51eSKate Stone enum class PyObjectType {
752c1f46dcSZachary Turner   Unknown,
762c1f46dcSZachary Turner   None,
77b81d715cSTatyana Krasnukha   Boolean,
782c1f46dcSZachary Turner   Integer,
792c1f46dcSZachary Turner   Dictionary,
802c1f46dcSZachary Turner   List,
819c40264fSZachary Turner   String,
825a72c02bSZachary Turner   Bytes,
83f9d6d204SZachary Turner   ByteArray,
847841efbbSZachary Turner   Module,
85a1405147SZachary Turner   Callable,
86a1405147SZachary Turner   Tuple,
879c40264fSZachary Turner   File
882c1f46dcSZachary Turner };
892c1f46dcSZachary Turner 
90b9c1b51eSKate Stone enum class PyRefType {
91f8b22f8fSZachary Turner   Borrowed, // We are not given ownership of the incoming PyObject.
92f8b22f8fSZachary Turner             // We cannot safely hold it without calling Py_INCREF.
93f8b22f8fSZachary Turner   Owned     // We have ownership of the incoming PyObject.  We should
94f8b22f8fSZachary Turner             // not call Py_INCREF.
95f8b22f8fSZachary Turner };
96f8b22f8fSZachary Turner 
97*085328eeSLawrence D'Anna namespace python {
98*085328eeSLawrence D'Anna 
99*085328eeSLawrence D'Anna // Take a reference that you already own, and turn it into
100*085328eeSLawrence D'Anna // a PythonObject.
101*085328eeSLawrence D'Anna //
102*085328eeSLawrence D'Anna // Most python API methods will return a +1 reference
103*085328eeSLawrence D'Anna // if they succeed or NULL if and only if
104*085328eeSLawrence D'Anna // they set an exception.   Use this to collect such return
105*085328eeSLawrence D'Anna // values, after checking for NULL.
106*085328eeSLawrence D'Anna //
107*085328eeSLawrence D'Anna // If T is not just PythonObject, then obj must be already be
108*085328eeSLawrence D'Anna // checked to be of the correct type.
109*085328eeSLawrence D'Anna template <typename T> T Take(PyObject *obj) {
110*085328eeSLawrence D'Anna   assert(obj);
111*085328eeSLawrence D'Anna   assert(!PyErr_Occurred());
112*085328eeSLawrence D'Anna   T thing(PyRefType::Owned, obj);
113*085328eeSLawrence D'Anna   assert(thing.IsValid());
114*085328eeSLawrence D'Anna   return std::move(thing);
115*085328eeSLawrence D'Anna }
116*085328eeSLawrence D'Anna 
117*085328eeSLawrence D'Anna // Retain a reference you have borrowed, and turn it into
118*085328eeSLawrence D'Anna // a PythonObject.
119*085328eeSLawrence D'Anna //
120*085328eeSLawrence D'Anna // A minority of python APIs return a borrowed reference
121*085328eeSLawrence D'Anna // instead of a +1.   They will also return NULL if and only
122*085328eeSLawrence D'Anna // if they set an exception.   Use this to collect such return
123*085328eeSLawrence D'Anna // values, after checking for NULL.
124*085328eeSLawrence D'Anna //
125*085328eeSLawrence D'Anna // If T is not just PythonObject, then obj must be already be
126*085328eeSLawrence D'Anna // checked to be of the correct type.
127*085328eeSLawrence D'Anna template <typename T> T Retain(PyObject *obj) {
128*085328eeSLawrence D'Anna   assert(obj);
129*085328eeSLawrence D'Anna   assert(!PyErr_Occurred());
130*085328eeSLawrence D'Anna   T thing(PyRefType::Borrowed, obj);
131*085328eeSLawrence D'Anna   assert(thing.IsValid());
132*085328eeSLawrence D'Anna   return std::move(thing);
133*085328eeSLawrence D'Anna }
134*085328eeSLawrence D'Anna 
135*085328eeSLawrence D'Anna } // namespace python
136*085328eeSLawrence D'Anna 
137b9c1b51eSKate Stone enum class PyInitialValue { Invalid, Empty };
138f8b22f8fSZachary Turner 
139*085328eeSLawrence D'Anna template <typename T, typename Enable = void> struct PythonFormat;
140*085328eeSLawrence D'Anna 
141*085328eeSLawrence D'Anna template <> struct PythonFormat<unsigned long long> {
142*085328eeSLawrence D'Anna   static constexpr char format = 'K';
143*085328eeSLawrence D'Anna   static auto get(unsigned long long value) { return value; }
144*085328eeSLawrence D'Anna };
145*085328eeSLawrence D'Anna 
146*085328eeSLawrence D'Anna template <> struct PythonFormat<long long> {
147*085328eeSLawrence D'Anna   static constexpr char format = 'L';
148*085328eeSLawrence D'Anna   static auto get(long long value) { return value; }
149*085328eeSLawrence D'Anna };
150*085328eeSLawrence D'Anna 
151*085328eeSLawrence D'Anna template <typename T>
152*085328eeSLawrence D'Anna struct PythonFormat<
153*085328eeSLawrence D'Anna     T, typename std::enable_if<std::is_base_of<PythonObject, T>::value>::type> {
154*085328eeSLawrence D'Anna   static constexpr char format = 'O';
155*085328eeSLawrence D'Anna   static auto get(const T &value) { return value.get(); }
156*085328eeSLawrence D'Anna };
157*085328eeSLawrence D'Anna 
158b9c1b51eSKate Stone class PythonObject {
1592c1f46dcSZachary Turner public:
160b9c1b51eSKate Stone   PythonObject() : m_py_obj(nullptr) {}
1612c1f46dcSZachary Turner 
162b9c1b51eSKate Stone   PythonObject(PyRefType type, PyObject *py_obj) : m_py_obj(nullptr) {
163f8b22f8fSZachary Turner     Reset(type, py_obj);
1642c1f46dcSZachary Turner   }
1652c1f46dcSZachary Turner 
166b9c1b51eSKate Stone   PythonObject(const PythonObject &rhs) : m_py_obj(nullptr) { Reset(rhs); }
1672c1f46dcSZachary Turner 
168*085328eeSLawrence D'Anna   PythonObject(PythonObject &&rhs) {
169*085328eeSLawrence D'Anna     m_py_obj = rhs.m_py_obj;
170*085328eeSLawrence D'Anna     rhs.m_py_obj = nullptr;
171*085328eeSLawrence D'Anna   }
172*085328eeSLawrence D'Anna 
173b9c1b51eSKate Stone   virtual ~PythonObject() { Reset(); }
1742c1f46dcSZachary Turner 
175b9c1b51eSKate Stone   void Reset() {
176f8b22f8fSZachary Turner     // Avoid calling the virtual method since it's not necessary
177f8b22f8fSZachary Turner     // to actually validate the type of the PyObject if we're
178f8b22f8fSZachary Turner     // just setting to null.
179*085328eeSLawrence D'Anna     if (m_py_obj && Py_IsInitialized())
180*085328eeSLawrence D'Anna       Py_DECREF(m_py_obj);
181f8b22f8fSZachary Turner     m_py_obj = nullptr;
1822c1f46dcSZachary Turner   }
183f8b22f8fSZachary Turner 
184b9c1b51eSKate Stone   void Reset(const PythonObject &rhs) {
185f8b22f8fSZachary Turner     // Avoid calling the virtual method if it's not necessary
186f8b22f8fSZachary Turner     // to actually validate the type of the PyObject.
18760c24f70SZachary Turner     if (!rhs.IsValid())
188f8b22f8fSZachary Turner       Reset();
189f8b22f8fSZachary Turner     else
190f8b22f8fSZachary Turner       Reset(PyRefType::Borrowed, rhs.m_py_obj);
191f8b22f8fSZachary Turner   }
192f8b22f8fSZachary Turner 
193f8b22f8fSZachary Turner   // PythonObject is implicitly convertible to PyObject *, which will call the
194f8b22f8fSZachary Turner   // wrong overload.  We want to explicitly disallow this, since a PyObject
195f8b22f8fSZachary Turner   // *always* owns its reference.  Therefore the overload which takes a
196f8b22f8fSZachary Turner   // PyRefType doesn't make sense, and the copy constructor should be used.
197b9c1b51eSKate Stone   void Reset(PyRefType type, const PythonObject &ref) = delete;
198f8b22f8fSZachary Turner 
199*085328eeSLawrence D'Anna   // FIXME We shouldn't have virtual anything.  PythonObject should be a
200*085328eeSLawrence D'Anna   // strictly pass-by-value type.
201b9c1b51eSKate Stone   virtual void Reset(PyRefType type, PyObject *py_obj) {
202f8b22f8fSZachary Turner     if (py_obj == m_py_obj)
203f8b22f8fSZachary Turner       return;
204f8b22f8fSZachary Turner 
205f8b22f8fSZachary Turner     if (Py_IsInitialized())
206f8b22f8fSZachary Turner       Py_XDECREF(m_py_obj);
207f8b22f8fSZachary Turner 
208f8b22f8fSZachary Turner     m_py_obj = py_obj;
209f8b22f8fSZachary Turner 
210f8b22f8fSZachary Turner     // If this is a borrowed reference, we need to convert it to
211f8b22f8fSZachary Turner     // an owned reference by incrementing it.  If it is an owned
212f8b22f8fSZachary Turner     // reference (for example the caller allocated it with PyDict_New()
213f8b22f8fSZachary Turner     // then we must *not* increment it.
214*085328eeSLawrence D'Anna     if (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed)
215f8b22f8fSZachary Turner       Py_XINCREF(m_py_obj);
2162c1f46dcSZachary Turner   }
2172c1f46dcSZachary Turner 
218b9c1b51eSKate Stone   void Dump() const {
2192c1f46dcSZachary Turner     if (m_py_obj)
2202c1f46dcSZachary Turner       _PyObject_Dump(m_py_obj);
2212c1f46dcSZachary Turner     else
2222c1f46dcSZachary Turner       puts("NULL");
2232c1f46dcSZachary Turner   }
2242c1f46dcSZachary Turner 
225b9c1b51eSKate Stone   void Dump(Stream &strm) const;
2262c1f46dcSZachary Turner 
227b9c1b51eSKate Stone   PyObject *get() const { return m_py_obj; }
2282c1f46dcSZachary Turner 
229b9c1b51eSKate Stone   PyObject *release() {
23060c24f70SZachary Turner     PyObject *result = m_py_obj;
23160c24f70SZachary Turner     m_py_obj = nullptr;
23260c24f70SZachary Turner     return result;
23360c24f70SZachary Turner   }
23460c24f70SZachary Turner 
235b9c1b51eSKate Stone   PythonObject &operator=(const PythonObject &other) {
236f8b22f8fSZachary Turner     Reset(PyRefType::Borrowed, other.get());
237f8b22f8fSZachary Turner     return *this;
2382c1f46dcSZachary Turner   }
2392c1f46dcSZachary Turner 
240*085328eeSLawrence D'Anna   void Reset(PythonObject &&other) {
241*085328eeSLawrence D'Anna     Reset();
242*085328eeSLawrence D'Anna     m_py_obj = other.m_py_obj;
243*085328eeSLawrence D'Anna     other.m_py_obj = nullptr;
244*085328eeSLawrence D'Anna   }
245*085328eeSLawrence D'Anna 
246*085328eeSLawrence D'Anna   PythonObject &operator=(PythonObject &&other) {
247*085328eeSLawrence D'Anna     Reset(std::move(other));
248*085328eeSLawrence D'Anna     return *this;
249*085328eeSLawrence D'Anna   }
250*085328eeSLawrence D'Anna 
251b9c1b51eSKate Stone   PyObjectType GetObjectType() const;
2527841efbbSZachary Turner 
253b9c1b51eSKate Stone   PythonString Repr() const;
2547841efbbSZachary Turner 
255b9c1b51eSKate Stone   PythonString Str() const;
2567841efbbSZachary Turner 
257b9c1b51eSKate Stone   static PythonObject ResolveNameWithDictionary(llvm::StringRef name,
258b9c1b51eSKate Stone                                                 const PythonDictionary &dict);
2597841efbbSZachary Turner 
260b58fb2f4SZachary Turner   template <typename T>
261b9c1b51eSKate Stone   static T ResolveNameWithDictionary(llvm::StringRef name,
262b9c1b51eSKate Stone                                      const PythonDictionary &dict) {
263b58fb2f4SZachary Turner     return ResolveNameWithDictionary(name, dict).AsType<T>();
264b58fb2f4SZachary Turner   }
265b58fb2f4SZachary Turner 
266b9c1b51eSKate Stone   PythonObject ResolveName(llvm::StringRef name) const;
2677841efbbSZachary Turner 
268b9c1b51eSKate Stone   template <typename T> T ResolveName(llvm::StringRef name) const {
269b58fb2f4SZachary Turner     return ResolveName(name).AsType<T>();
270b58fb2f4SZachary Turner   }
271b58fb2f4SZachary Turner 
272b9c1b51eSKate Stone   bool HasAttribute(llvm::StringRef attribute) const;
2739c40264fSZachary Turner 
274b9c1b51eSKate Stone   PythonObject GetAttributeValue(llvm::StringRef attribute) const;
2757d6d218eSZachary Turner 
276*085328eeSLawrence D'Anna   bool IsNone() const { return m_py_obj == Py_None; }
277f8b22f8fSZachary Turner 
278*085328eeSLawrence D'Anna   bool IsValid() const { return m_py_obj != nullptr; }
279f8b22f8fSZachary Turner 
280*085328eeSLawrence D'Anna   bool IsAllocated() const { return IsValid() && !IsNone(); }
281*085328eeSLawrence D'Anna 
282*085328eeSLawrence D'Anna   explicit operator bool() const { return IsValid() && !IsNone(); }
2832c1f46dcSZachary Turner 
284b9c1b51eSKate Stone   template <typename T> T AsType() const {
2857d6d218eSZachary Turner     if (!T::Check(m_py_obj))
2867d6d218eSZachary Turner       return T();
2877d6d218eSZachary Turner     return T(PyRefType::Borrowed, m_py_obj);
2887d6d218eSZachary Turner   }
2897d6d218eSZachary Turner 
290b9c1b51eSKate Stone   StructuredData::ObjectSP CreateStructuredObject() const;
2912c1f46dcSZachary Turner 
2922c1f46dcSZachary Turner protected:
293*085328eeSLawrence D'Anna   static llvm::Error nullDeref() {
294*085328eeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
295*085328eeSLawrence D'Anna                                    "A NULL PyObject* was dereferenced");
296*085328eeSLawrence D'Anna   }
297*085328eeSLawrence D'Anna   static llvm::Error exception(const char *s = nullptr) {
298*085328eeSLawrence D'Anna     return llvm::make_error<PythonException>(s);
299*085328eeSLawrence D'Anna   }
300*085328eeSLawrence D'Anna 
301*085328eeSLawrence D'Anna public:
302*085328eeSLawrence D'Anna   template <typename... T>
303*085328eeSLawrence D'Anna   llvm::Expected<PythonObject> CallMethod(const char *name,
304*085328eeSLawrence D'Anna                                           const T &... t) const {
305*085328eeSLawrence D'Anna     const char format[] = {'(', PythonFormat<T>::format..., ')', 0};
306*085328eeSLawrence D'Anna #if PY_MAJOR_VERSION < 3
307*085328eeSLawrence D'Anna     PyObject *obj = PyObject_CallMethod(m_py_obj, const_cast<char *>(name),
308*085328eeSLawrence D'Anna                                         const_cast<char *>(format),
309*085328eeSLawrence D'Anna                                         PythonFormat<T>::get(t)...);
310*085328eeSLawrence D'Anna #else
311*085328eeSLawrence D'Anna     PyObject *obj =
312*085328eeSLawrence D'Anna         PyObject_CallMethod(m_py_obj, name, format, PythonFormat<T>::get(t)...);
313*085328eeSLawrence D'Anna #endif
314*085328eeSLawrence D'Anna     if (!obj)
315*085328eeSLawrence D'Anna       return exception();
316*085328eeSLawrence D'Anna     return python::Take<PythonObject>(obj);
317*085328eeSLawrence D'Anna   }
318*085328eeSLawrence D'Anna 
319*085328eeSLawrence D'Anna   llvm::Expected<PythonObject> GetAttribute(const char *name) const {
320*085328eeSLawrence D'Anna     if (!m_py_obj)
321*085328eeSLawrence D'Anna       return nullDeref();
322*085328eeSLawrence D'Anna     PyObject *obj = PyObject_GetAttrString(m_py_obj, name);
323*085328eeSLawrence D'Anna     if (!obj)
324*085328eeSLawrence D'Anna       return exception();
325*085328eeSLawrence D'Anna     return python::Take<PythonObject>(obj);
326*085328eeSLawrence D'Anna   }
327*085328eeSLawrence D'Anna 
328*085328eeSLawrence D'Anna   llvm::Expected<bool> IsTrue() {
329*085328eeSLawrence D'Anna     if (!m_py_obj)
330*085328eeSLawrence D'Anna       return nullDeref();
331*085328eeSLawrence D'Anna     int r = PyObject_IsTrue(m_py_obj);
332*085328eeSLawrence D'Anna     if (r < 0)
333*085328eeSLawrence D'Anna       return exception();
334*085328eeSLawrence D'Anna     return !!r;
335*085328eeSLawrence D'Anna   }
336*085328eeSLawrence D'Anna 
337*085328eeSLawrence D'Anna   llvm::Expected<long long> AsLongLong() {
338*085328eeSLawrence D'Anna     if (!m_py_obj)
339*085328eeSLawrence D'Anna       return nullDeref();
340*085328eeSLawrence D'Anna     assert(!PyErr_Occurred());
341*085328eeSLawrence D'Anna     long long r = PyLong_AsLongLong(m_py_obj);
342*085328eeSLawrence D'Anna     if (PyErr_Occurred())
343*085328eeSLawrence D'Anna       return exception();
344*085328eeSLawrence D'Anna     return r;
345*085328eeSLawrence D'Anna   }
346*085328eeSLawrence D'Anna 
347*085328eeSLawrence D'Anna   llvm::Expected<bool> IsInstance(const PythonObject &cls) {
348*085328eeSLawrence D'Anna     if (!m_py_obj || !cls.IsValid())
349*085328eeSLawrence D'Anna       return nullDeref();
350*085328eeSLawrence D'Anna     int r = PyObject_IsInstance(m_py_obj, cls.get());
351*085328eeSLawrence D'Anna     if (r < 0)
352*085328eeSLawrence D'Anna       return exception();
353*085328eeSLawrence D'Anna     return !!r;
354*085328eeSLawrence D'Anna   }
355*085328eeSLawrence D'Anna 
356*085328eeSLawrence D'Anna protected:
3572c1f46dcSZachary Turner   PyObject *m_py_obj;
3582c1f46dcSZachary Turner };
3592c1f46dcSZachary Turner 
360*085328eeSLawrence D'Anna namespace python {
361*085328eeSLawrence D'Anna 
362*085328eeSLawrence D'Anna // This is why C++ needs monads.
363*085328eeSLawrence D'Anna template <typename T> llvm::Expected<T> As(llvm::Expected<PythonObject> &&obj) {
364*085328eeSLawrence D'Anna   if (!obj)
365*085328eeSLawrence D'Anna     return obj.takeError();
366*085328eeSLawrence D'Anna   if (!T::Check(obj.get().get()))
367*085328eeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
368*085328eeSLawrence D'Anna                                    "type error");
369*085328eeSLawrence D'Anna   return T(PyRefType::Borrowed, std::move(obj.get().get()));
370*085328eeSLawrence D'Anna }
371*085328eeSLawrence D'Anna 
372*085328eeSLawrence D'Anna template <> llvm::Expected<bool> As<bool>(llvm::Expected<PythonObject> &&obj);
373*085328eeSLawrence D'Anna 
374*085328eeSLawrence D'Anna template <>
375*085328eeSLawrence D'Anna llvm::Expected<long long> As<long long>(llvm::Expected<PythonObject> &&obj);
376*085328eeSLawrence D'Anna 
377*085328eeSLawrence D'Anna } // namespace python
378*085328eeSLawrence D'Anna 
379b9c1b51eSKate Stone class PythonBytes : public PythonObject {
3805a72c02bSZachary Turner public:
3815a72c02bSZachary Turner   PythonBytes();
3825a72c02bSZachary Turner   explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes);
3835a72c02bSZachary Turner   PythonBytes(const uint8_t *bytes, size_t length);
3845a72c02bSZachary Turner   PythonBytes(PyRefType type, PyObject *o);
3855a72c02bSZachary Turner 
3865a72c02bSZachary Turner   ~PythonBytes() override;
3875a72c02bSZachary Turner 
388b9c1b51eSKate Stone   static bool Check(PyObject *py_obj);
3895a72c02bSZachary Turner 
3905a72c02bSZachary Turner   // Bring in the no-argument base class version
3915a72c02bSZachary Turner   using PythonObject::Reset;
3925a72c02bSZachary Turner 
393b9c1b51eSKate Stone   void Reset(PyRefType type, PyObject *py_obj) override;
3945a72c02bSZachary Turner 
395b9c1b51eSKate Stone   llvm::ArrayRef<uint8_t> GetBytes() const;
3965a72c02bSZachary Turner 
397b9c1b51eSKate Stone   size_t GetSize() const;
3985a72c02bSZachary Turner 
399b9c1b51eSKate Stone   void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
4005a72c02bSZachary Turner 
401b9c1b51eSKate Stone   StructuredData::StringSP CreateStructuredString() const;
4025a72c02bSZachary Turner };
4035a72c02bSZachary Turner 
404b9c1b51eSKate Stone class PythonByteArray : public PythonObject {
405f9d6d204SZachary Turner public:
406f9d6d204SZachary Turner   PythonByteArray();
407f9d6d204SZachary Turner   explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes);
408f9d6d204SZachary Turner   PythonByteArray(const uint8_t *bytes, size_t length);
409f9d6d204SZachary Turner   PythonByteArray(PyRefType type, PyObject *o);
410f9d6d204SZachary Turner   PythonByteArray(const PythonBytes &object);
411f9d6d204SZachary Turner 
412f9d6d204SZachary Turner   ~PythonByteArray() override;
413f9d6d204SZachary Turner 
414b9c1b51eSKate Stone   static bool Check(PyObject *py_obj);
415f9d6d204SZachary Turner 
416f9d6d204SZachary Turner   // Bring in the no-argument base class version
417f9d6d204SZachary Turner   using PythonObject::Reset;
418f9d6d204SZachary Turner 
419b9c1b51eSKate Stone   void Reset(PyRefType type, PyObject *py_obj) override;
420f9d6d204SZachary Turner 
421b9c1b51eSKate Stone   llvm::ArrayRef<uint8_t> GetBytes() const;
422f9d6d204SZachary Turner 
423b9c1b51eSKate Stone   size_t GetSize() const;
424f9d6d204SZachary Turner 
425b9c1b51eSKate Stone   void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
426f9d6d204SZachary Turner 
427b9c1b51eSKate Stone   StructuredData::StringSP CreateStructuredString() const;
428f9d6d204SZachary Turner };
429f9d6d204SZachary Turner 
430b9c1b51eSKate Stone class PythonString : public PythonObject {
4312c1f46dcSZachary Turner public:
432*085328eeSLawrence D'Anna   static llvm::Expected<PythonString> FromUTF8(llvm::StringRef string);
433*085328eeSLawrence D'Anna 
4342c1f46dcSZachary Turner   PythonString();
435*085328eeSLawrence D'Anna   explicit PythonString(llvm::StringRef string); // safe, null on error
43687f47729SZachary Turner   PythonString(PyRefType type, PyObject *o);
437edb35d95SEugene Zelenko 
438f8b22f8fSZachary Turner   ~PythonString() override;
4392c1f46dcSZachary Turner 
44022c8efcdSZachary Turner   static bool Check(PyObject *py_obj);
44122c8efcdSZachary Turner 
442f8b22f8fSZachary Turner   // Bring in the no-argument base class version
443f8b22f8fSZachary Turner   using PythonObject::Reset;
444f8b22f8fSZachary Turner 
445f8b22f8fSZachary Turner   void Reset(PyRefType type, PyObject *py_obj) override;
4462c1f46dcSZachary Turner 
447*085328eeSLawrence D'Anna   llvm::StringRef GetString() const; // safe, empty string on error
448*085328eeSLawrence D'Anna 
449*085328eeSLawrence D'Anna   llvm::Expected<llvm::StringRef> AsUTF8() const;
4502c1f46dcSZachary Turner 
451b9c1b51eSKate Stone   size_t GetSize() const;
4522c1f46dcSZachary Turner 
453*085328eeSLawrence D'Anna   void SetString(llvm::StringRef string); // safe, null on error
4542c1f46dcSZachary Turner 
4552c1f46dcSZachary Turner   StructuredData::StringSP CreateStructuredString() const;
4562c1f46dcSZachary Turner };
4572c1f46dcSZachary Turner 
458b9c1b51eSKate Stone class PythonInteger : public PythonObject {
4592c1f46dcSZachary Turner public:
4602c1f46dcSZachary Turner   PythonInteger();
46187f47729SZachary Turner   explicit PythonInteger(int64_t value);
462f8b22f8fSZachary Turner   PythonInteger(PyRefType type, PyObject *o);
463edb35d95SEugene Zelenko 
464f8b22f8fSZachary Turner   ~PythonInteger() override;
4652c1f46dcSZachary Turner 
46622c8efcdSZachary Turner   static bool Check(PyObject *py_obj);
46722c8efcdSZachary Turner 
468f8b22f8fSZachary Turner   // Bring in the no-argument base class version
469f8b22f8fSZachary Turner   using PythonObject::Reset;
470f8b22f8fSZachary Turner 
471f8b22f8fSZachary Turner   void Reset(PyRefType type, PyObject *py_obj) override;
4722c1f46dcSZachary Turner 
4732c1f46dcSZachary Turner   int64_t GetInteger() const;
4742c1f46dcSZachary Turner 
475b9c1b51eSKate Stone   void SetInteger(int64_t value);
4762c1f46dcSZachary Turner 
4772c1f46dcSZachary Turner   StructuredData::IntegerSP CreateStructuredInteger() const;
4782c1f46dcSZachary Turner };
4792c1f46dcSZachary Turner 
480b81d715cSTatyana Krasnukha class PythonBoolean : public PythonObject {
481b81d715cSTatyana Krasnukha public:
482b81d715cSTatyana Krasnukha   PythonBoolean() = default;
483b81d715cSTatyana Krasnukha   explicit PythonBoolean(bool value);
484b81d715cSTatyana Krasnukha   PythonBoolean(PyRefType type, PyObject *o);
485b81d715cSTatyana Krasnukha 
486b81d715cSTatyana Krasnukha   ~PythonBoolean() override = default;
487b81d715cSTatyana Krasnukha 
488b81d715cSTatyana Krasnukha   static bool Check(PyObject *py_obj);
489b81d715cSTatyana Krasnukha 
490b81d715cSTatyana Krasnukha   // Bring in the no-argument base class version
491b81d715cSTatyana Krasnukha   using PythonObject::Reset;
492b81d715cSTatyana Krasnukha 
493b81d715cSTatyana Krasnukha   void Reset(PyRefType type, PyObject *py_obj) override;
494b81d715cSTatyana Krasnukha 
495b81d715cSTatyana Krasnukha   bool GetValue() const;
496b81d715cSTatyana Krasnukha 
497b81d715cSTatyana Krasnukha   void SetValue(bool value);
498b81d715cSTatyana Krasnukha 
499b81d715cSTatyana Krasnukha   StructuredData::BooleanSP CreateStructuredBoolean() const;
500b81d715cSTatyana Krasnukha };
501b81d715cSTatyana Krasnukha 
502b9c1b51eSKate Stone class PythonList : public PythonObject {
5032c1f46dcSZachary Turner public:
504a1405147SZachary Turner   PythonList() {}
50587f47729SZachary Turner   explicit PythonList(PyInitialValue value);
50687f47729SZachary Turner   explicit PythonList(int list_size);
507f8b22f8fSZachary Turner   PythonList(PyRefType type, PyObject *o);
508edb35d95SEugene Zelenko 
509f8b22f8fSZachary Turner   ~PythonList() override;
5102c1f46dcSZachary Turner 
51122c8efcdSZachary Turner   static bool Check(PyObject *py_obj);
51222c8efcdSZachary Turner 
513f8b22f8fSZachary Turner   // Bring in the no-argument base class version
514f8b22f8fSZachary Turner   using PythonObject::Reset;
515f8b22f8fSZachary Turner 
516f8b22f8fSZachary Turner   void Reset(PyRefType type, PyObject *py_obj) override;
5172c1f46dcSZachary Turner 
5182c1f46dcSZachary Turner   uint32_t GetSize() const;
5192c1f46dcSZachary Turner 
5202c1f46dcSZachary Turner   PythonObject GetItemAtIndex(uint32_t index) const;
5212c1f46dcSZachary Turner 
522f8b22f8fSZachary Turner   void SetItemAtIndex(uint32_t index, const PythonObject &object);
5232c1f46dcSZachary Turner 
524f8b22f8fSZachary Turner   void AppendItem(const PythonObject &object);
5252c1f46dcSZachary Turner 
5262c1f46dcSZachary Turner   StructuredData::ArraySP CreateStructuredArray() const;
5272c1f46dcSZachary Turner };
5282c1f46dcSZachary Turner 
529b9c1b51eSKate Stone class PythonTuple : public PythonObject {
530a1405147SZachary Turner public:
531a1405147SZachary Turner   PythonTuple() {}
532a1405147SZachary Turner   explicit PythonTuple(PyInitialValue value);
533a1405147SZachary Turner   explicit PythonTuple(int tuple_size);
534a1405147SZachary Turner   PythonTuple(PyRefType type, PyObject *o);
535a1405147SZachary Turner   PythonTuple(std::initializer_list<PythonObject> objects);
536a1405147SZachary Turner   PythonTuple(std::initializer_list<PyObject *> objects);
537a1405147SZachary Turner 
538a1405147SZachary Turner   ~PythonTuple() override;
539a1405147SZachary Turner 
540a1405147SZachary Turner   static bool Check(PyObject *py_obj);
541a1405147SZachary Turner 
542a1405147SZachary Turner   // Bring in the no-argument base class version
543a1405147SZachary Turner   using PythonObject::Reset;
544a1405147SZachary Turner 
545a1405147SZachary Turner   void Reset(PyRefType type, PyObject *py_obj) override;
546a1405147SZachary Turner 
547a1405147SZachary Turner   uint32_t GetSize() const;
548a1405147SZachary Turner 
549a1405147SZachary Turner   PythonObject GetItemAtIndex(uint32_t index) const;
550a1405147SZachary Turner 
551a1405147SZachary Turner   void SetItemAtIndex(uint32_t index, const PythonObject &object);
552a1405147SZachary Turner 
553a1405147SZachary Turner   StructuredData::ArraySP CreateStructuredArray() const;
554a1405147SZachary Turner };
555a1405147SZachary Turner 
556b9c1b51eSKate Stone class PythonDictionary : public PythonObject {
5572c1f46dcSZachary Turner public:
558a1405147SZachary Turner   PythonDictionary() {}
55987f47729SZachary Turner   explicit PythonDictionary(PyInitialValue value);
560f8b22f8fSZachary Turner   PythonDictionary(PyRefType type, PyObject *o);
561edb35d95SEugene Zelenko 
562f8b22f8fSZachary Turner   ~PythonDictionary() override;
5632c1f46dcSZachary Turner 
56422c8efcdSZachary Turner   static bool Check(PyObject *py_obj);
56522c8efcdSZachary Turner 
566f8b22f8fSZachary Turner   // Bring in the no-argument base class version
567f8b22f8fSZachary Turner   using PythonObject::Reset;
568f8b22f8fSZachary Turner 
569f8b22f8fSZachary Turner   void Reset(PyRefType type, PyObject *py_obj) override;
5702c1f46dcSZachary Turner 
5712c1f46dcSZachary Turner   uint32_t GetSize() const;
5722c1f46dcSZachary Turner 
573f8b22f8fSZachary Turner   PythonList GetKeys() const;
5742c1f46dcSZachary Turner 
575f8b22f8fSZachary Turner   PythonObject GetItemForKey(const PythonObject &key) const;
576f8b22f8fSZachary Turner   void SetItemForKey(const PythonObject &key, const PythonObject &value);
5772c1f46dcSZachary Turner 
5782c1f46dcSZachary Turner   StructuredData::DictionarySP CreateStructuredDictionary() const;
5792c1f46dcSZachary Turner };
58087f47729SZachary Turner 
581b9c1b51eSKate Stone class PythonModule : public PythonObject {
5827841efbbSZachary Turner public:
5837841efbbSZachary Turner   PythonModule();
5847841efbbSZachary Turner   PythonModule(PyRefType type, PyObject *o);
5857841efbbSZachary Turner 
5867841efbbSZachary Turner   ~PythonModule() override;
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 
596*085328eeSLawrence D'Anna   // safe, returns invalid on error;
597*085328eeSLawrence D'Anna   static PythonModule ImportModule(llvm::StringRef name) {
598*085328eeSLawrence D'Anna     std::string s = name;
599*085328eeSLawrence D'Anna     auto mod = Import(s.c_str());
600*085328eeSLawrence D'Anna     if (!mod) {
601*085328eeSLawrence D'Anna       llvm::consumeError(mod.takeError());
602*085328eeSLawrence D'Anna       return PythonModule();
603*085328eeSLawrence D'Anna     }
604*085328eeSLawrence D'Anna     return std::move(mod.get());
605*085328eeSLawrence D'Anna   }
606*085328eeSLawrence D'Anna 
607*085328eeSLawrence D'Anna   static llvm::Expected<PythonModule> Import(const char *name);
608*085328eeSLawrence D'Anna 
609*085328eeSLawrence D'Anna   llvm::Expected<PythonObject> Get(const char *name);
6102419f1d5SZachary Turner 
6117841efbbSZachary Turner   // Bring in the no-argument base class version
6127841efbbSZachary Turner   using PythonObject::Reset;
6137841efbbSZachary Turner 
6147841efbbSZachary Turner   void Reset(PyRefType type, PyObject *py_obj) override;
6157841efbbSZachary Turner 
6167841efbbSZachary Turner   PythonDictionary GetDictionary() const;
6177841efbbSZachary Turner };
6187841efbbSZachary Turner 
619b9c1b51eSKate Stone class PythonCallable : public PythonObject {
620a1405147SZachary Turner public:
621b58fb2f4SZachary Turner   struct ArgInfo {
622b58fb2f4SZachary Turner     size_t count;
623a5d6765cSEnrico Granata     bool is_bound_method : 1;
624b58fb2f4SZachary Turner     bool has_varargs : 1;
625b58fb2f4SZachary Turner     bool has_kwargs : 1;
626b58fb2f4SZachary Turner   };
627b58fb2f4SZachary Turner 
628a1405147SZachary Turner   PythonCallable();
629a1405147SZachary Turner   PythonCallable(PyRefType type, PyObject *o);
630a1405147SZachary Turner 
631a1405147SZachary Turner   ~PythonCallable() override;
632a1405147SZachary Turner 
633b9c1b51eSKate Stone   static bool Check(PyObject *py_obj);
634a1405147SZachary Turner 
635a1405147SZachary Turner   // Bring in the no-argument base class version
636a1405147SZachary Turner   using PythonObject::Reset;
637a1405147SZachary Turner 
638b9c1b51eSKate Stone   void Reset(PyRefType type, PyObject *py_obj) override;
639a1405147SZachary Turner 
640b9c1b51eSKate Stone   ArgInfo GetNumArguments() const;
64127a14f19SJim Ingham 
64227a14f19SJim Ingham   // If the callable is a Py_Class, then find the number of arguments
64327a14f19SJim Ingham   // of the __init__ method.
64427a14f19SJim Ingham   ArgInfo GetNumInitArguments() const;
645b58fb2f4SZachary Turner 
646b9c1b51eSKate Stone   PythonObject operator()();
647a1405147SZachary Turner 
648b9c1b51eSKate Stone   PythonObject operator()(std::initializer_list<PyObject *> args);
649a1405147SZachary Turner 
650b9c1b51eSKate Stone   PythonObject operator()(std::initializer_list<PythonObject> args);
651b58fb2f4SZachary Turner 
652b58fb2f4SZachary Turner   template <typename Arg, typename... Args>
653b9c1b51eSKate Stone   PythonObject operator()(const Arg &arg, Args... args) {
654b58fb2f4SZachary Turner     return operator()({arg, args...});
655b58fb2f4SZachary Turner   }
656a1405147SZachary Turner };
657a1405147SZachary Turner 
658b9c1b51eSKate Stone class PythonFile : public PythonObject {
6599c40264fSZachary Turner public:
66032064024SZachary Turner   PythonFile();
661eda01c31SZachary Turner   PythonFile(File &file, const char *mode);
6629c40264fSZachary Turner   PythonFile(PyRefType type, PyObject *o);
663edb35d95SEugene Zelenko 
6649c40264fSZachary Turner   ~PythonFile() override;
6659c40264fSZachary Turner 
6669c40264fSZachary Turner   static bool Check(PyObject *py_obj);
6679c40264fSZachary Turner 
6689c40264fSZachary Turner   using PythonObject::Reset;
6699c40264fSZachary Turner 
6709c40264fSZachary Turner   void Reset(PyRefType type, PyObject *py_obj) override;
6719c40264fSZachary Turner   void Reset(File &file, const char *mode);
672eda01c31SZachary Turner 
6732fce1137SLawrence D'Anna   lldb::FileUP GetUnderlyingFile() const;
674*085328eeSLawrence D'Anna 
675*085328eeSLawrence D'Anna   llvm::Expected<lldb::FileSP> ConvertToFile(bool borrowed = false);
676*085328eeSLawrence D'Anna   llvm::Expected<lldb::FileSP>
677*085328eeSLawrence D'Anna   ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed = false);
6789c40264fSZachary Turner };
6799c40264fSZachary Turner 
680*085328eeSLawrence D'Anna class PythonException : public llvm::ErrorInfo<PythonException> {
681*085328eeSLawrence D'Anna private:
682*085328eeSLawrence D'Anna   PyObject *m_exception_type, *m_exception, *m_traceback;
683*085328eeSLawrence D'Anna   PyObject *m_repr_bytes;
684*085328eeSLawrence D'Anna 
685*085328eeSLawrence D'Anna public:
686*085328eeSLawrence D'Anna   static char ID;
687*085328eeSLawrence D'Anna   const char *toCString() const;
688*085328eeSLawrence D'Anna   PythonException(const char *caller = nullptr);
689*085328eeSLawrence D'Anna   void Restore();
690*085328eeSLawrence D'Anna   ~PythonException();
691*085328eeSLawrence D'Anna   void log(llvm::raw_ostream &OS) const override;
692*085328eeSLawrence D'Anna   std::error_code convertToErrorCode() const override;
693*085328eeSLawrence D'Anna };
694*085328eeSLawrence D'Anna 
695*085328eeSLawrence D'Anna // This extracts the underlying T out of an Expected<T> and returns it.
696*085328eeSLawrence D'Anna // If the Expected is an Error instead of a T, that error will be converted
697*085328eeSLawrence D'Anna // into a python exception, and this will return a default-constructed T.
698*085328eeSLawrence D'Anna //
699*085328eeSLawrence D'Anna // This is appropriate for use right at the boundary of python calling into
700*085328eeSLawrence D'Anna // C++, such as in a SWIG typemap.   In such a context you should simply
701*085328eeSLawrence D'Anna // check if the returned T is valid, and if it is, return a NULL back
702*085328eeSLawrence D'Anna // to python.   This will result in the Error being raised as an exception
703*085328eeSLawrence D'Anna // from python code's point of view.
704*085328eeSLawrence D'Anna //
705*085328eeSLawrence D'Anna // For example:
706*085328eeSLawrence D'Anna // ```
707*085328eeSLawrence D'Anna // Expected<Foo *> efoop = some_cpp_function();
708*085328eeSLawrence D'Anna // Foo *foop = unwrapOrSetPythonException(efoop);
709*085328eeSLawrence D'Anna // if (!foop)
710*085328eeSLawrence D'Anna //    return NULL;
711*085328eeSLawrence D'Anna // do_something(*foop);
712*085328eeSLawrence D'Anna //
713*085328eeSLawrence D'Anna // If the Error returned was itself created because a python exception was
714*085328eeSLawrence D'Anna // raised when C++ code called into python, then the original exception
715*085328eeSLawrence D'Anna // will be restored.   Otherwise a simple string exception will be raised.
716*085328eeSLawrence D'Anna template <typename T> T unwrapOrSetPythonException(llvm::Expected<T> expected) {
717*085328eeSLawrence D'Anna   if (expected)
718*085328eeSLawrence D'Anna     return expected.get();
719*085328eeSLawrence D'Anna   llvm::handleAllErrors(
720*085328eeSLawrence D'Anna       expected.takeError(), [](PythonException &E) { E.Restore(); },
721*085328eeSLawrence D'Anna       [](const llvm::ErrorInfoBase &E) {
722*085328eeSLawrence D'Anna         PyErr_SetString(PyExc_Exception, E.message().c_str());
723*085328eeSLawrence D'Anna       });
724*085328eeSLawrence D'Anna   return T();
725*085328eeSLawrence D'Anna }
726*085328eeSLawrence D'Anna 
7272c1f46dcSZachary Turner } // namespace lldb_private
7282c1f46dcSZachary Turner 
729a281b42bSZachary Turner #endif
730d68983e3SPavel Labath 
731d68983e3SPavel Labath #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
732