xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h (revision be691f3bb6417f04a68938fadbcaee2d5795e764)
1061da546Spatrick //===-- PythonDataObjects.h--------------------------------------*- C++ -*-===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick //
10061da546Spatrick // !! FIXME FIXME FIXME !!
11061da546Spatrick //
12061da546Spatrick // Python APIs nearly all can return an exception.   They do this
13061da546Spatrick // by returning NULL, or -1, or some such value and setting
14061da546Spatrick // the exception state with PyErr_Set*().   Exceptions must be
15061da546Spatrick // handled before further python API functions are called.   Failure
16061da546Spatrick // to do so will result in asserts on debug builds of python.
17061da546Spatrick // It will also sometimes, but not usually result in crashes of
18061da546Spatrick // release builds.
19061da546Spatrick //
20061da546Spatrick // Nearly all the code in this header does not handle python exceptions
21061da546Spatrick // correctly.  It should all be converted to return Expected<> or
22061da546Spatrick // Error types to capture the exception.
23061da546Spatrick //
24061da546Spatrick // Everything in this file except functions that return Error or
25061da546Spatrick // Expected<> is considered deprecated and should not be
26061da546Spatrick // used in new code.  If you need to use it, fix it first.
27061da546Spatrick //
28061da546Spatrick //
29061da546Spatrick // TODOs for this file
30061da546Spatrick //
31061da546Spatrick // * Make all methods safe for exceptions.
32061da546Spatrick //
33061da546Spatrick // * Eliminate method signatures that must translate exceptions into
34061da546Spatrick //   empty objects or NULLs.   Almost everything here should return
35061da546Spatrick //   Expected<>.   It should be acceptable for certain operations that
36061da546Spatrick //   can never fail to assert instead, such as the creation of
37061da546Spatrick //   PythonString from a string literal.
38061da546Spatrick //
39dda28197Spatrick // * Eliminate Reset(), and make all non-default constructors private.
40061da546Spatrick //   Python objects should be created with Retain<> or Take<>, and they
41061da546Spatrick //   should be assigned with operator=
42061da546Spatrick //
43061da546Spatrick // * Eliminate default constructors, make python objects always
44061da546Spatrick //   nonnull, and use optionals where necessary.
45061da546Spatrick //
46061da546Spatrick 
47061da546Spatrick 
48061da546Spatrick #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
49061da546Spatrick #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
50061da546Spatrick 
51061da546Spatrick #include "lldb/Host/Config.h"
52061da546Spatrick 
53061da546Spatrick #if LLDB_ENABLE_PYTHON
54061da546Spatrick 
55061da546Spatrick // LLDB Python header must be included first
56061da546Spatrick #include "lldb-python.h"
57061da546Spatrick 
58061da546Spatrick #include "lldb/Host/File.h"
59061da546Spatrick #include "lldb/Utility/StructuredData.h"
60061da546Spatrick 
61061da546Spatrick #include "llvm/ADT/ArrayRef.h"
62061da546Spatrick 
63061da546Spatrick namespace lldb_private {
64061da546Spatrick namespace python {
65061da546Spatrick 
66061da546Spatrick class PythonObject;
67061da546Spatrick class PythonBytes;
68061da546Spatrick class PythonString;
69061da546Spatrick class PythonList;
70061da546Spatrick class PythonDictionary;
71061da546Spatrick class PythonInteger;
72061da546Spatrick class PythonException;
73061da546Spatrick 
74061da546Spatrick class StructuredPythonObject : public StructuredData::Generic {
75061da546Spatrick public:
76061da546Spatrick   StructuredPythonObject() : StructuredData::Generic() {}
77061da546Spatrick 
78061da546Spatrick   StructuredPythonObject(void *obj) : StructuredData::Generic(obj) {
79061da546Spatrick     Py_XINCREF(GetValue());
80061da546Spatrick   }
81061da546Spatrick 
82061da546Spatrick   ~StructuredPythonObject() override {
83061da546Spatrick     if (Py_IsInitialized())
84061da546Spatrick       Py_XDECREF(GetValue());
85061da546Spatrick     SetValue(nullptr);
86061da546Spatrick   }
87061da546Spatrick 
88061da546Spatrick   bool IsValid() const override { return GetValue() && GetValue() != Py_None; }
89061da546Spatrick 
90061da546Spatrick   void Serialize(llvm::json::OStream &s) const override;
91061da546Spatrick 
92061da546Spatrick private:
93dda28197Spatrick   StructuredPythonObject(const StructuredPythonObject &) = delete;
94dda28197Spatrick   const StructuredPythonObject &
95dda28197Spatrick   operator=(const StructuredPythonObject &) = delete;
96061da546Spatrick };
97061da546Spatrick 
98061da546Spatrick enum class PyObjectType {
99061da546Spatrick   Unknown,
100061da546Spatrick   None,
101061da546Spatrick   Boolean,
102061da546Spatrick   Integer,
103061da546Spatrick   Dictionary,
104061da546Spatrick   List,
105061da546Spatrick   String,
106061da546Spatrick   Bytes,
107061da546Spatrick   ByteArray,
108061da546Spatrick   Module,
109061da546Spatrick   Callable,
110061da546Spatrick   Tuple,
111061da546Spatrick   File
112061da546Spatrick };
113061da546Spatrick 
114061da546Spatrick enum class PyRefType {
115061da546Spatrick   Borrowed, // We are not given ownership of the incoming PyObject.
116061da546Spatrick             // We cannot safely hold it without calling Py_INCREF.
117061da546Spatrick   Owned     // We have ownership of the incoming PyObject.  We should
118061da546Spatrick             // not call Py_INCREF.
119061da546Spatrick };
120061da546Spatrick 
121061da546Spatrick 
122061da546Spatrick // Take a reference that you already own, and turn it into
123061da546Spatrick // a PythonObject.
124061da546Spatrick //
125061da546Spatrick // Most python API methods will return a +1 reference
126061da546Spatrick // if they succeed or NULL if and only if
127061da546Spatrick // they set an exception.   Use this to collect such return
128061da546Spatrick // values, after checking for NULL.
129061da546Spatrick //
130061da546Spatrick // If T is not just PythonObject, then obj must be already be
131061da546Spatrick // checked to be of the correct type.
132061da546Spatrick template <typename T> T Take(PyObject *obj) {
133061da546Spatrick   assert(obj);
134061da546Spatrick   assert(!PyErr_Occurred());
135061da546Spatrick   T thing(PyRefType::Owned, obj);
136061da546Spatrick   assert(thing.IsValid());
137061da546Spatrick   return thing;
138061da546Spatrick }
139061da546Spatrick 
140061da546Spatrick // Retain a reference you have borrowed, and turn it into
141061da546Spatrick // a PythonObject.
142061da546Spatrick //
143061da546Spatrick // A minority of python APIs return a borrowed reference
144061da546Spatrick // instead of a +1.   They will also return NULL if and only
145061da546Spatrick // if they set an exception.   Use this to collect such return
146061da546Spatrick // values, after checking for NULL.
147061da546Spatrick //
148061da546Spatrick // If T is not just PythonObject, then obj must be already be
149061da546Spatrick // checked to be of the correct type.
150061da546Spatrick template <typename T> T Retain(PyObject *obj) {
151061da546Spatrick   assert(obj);
152061da546Spatrick   assert(!PyErr_Occurred());
153061da546Spatrick   T thing(PyRefType::Borrowed, obj);
154061da546Spatrick   assert(thing.IsValid());
155061da546Spatrick   return thing;
156061da546Spatrick }
157061da546Spatrick 
158061da546Spatrick // This class can be used like a utility function to convert from
159061da546Spatrick // a llvm-friendly Twine into a null-terminated const char *,
160061da546Spatrick // which is the form python C APIs want their strings in.
161061da546Spatrick //
162061da546Spatrick // Example:
163061da546Spatrick // const llvm::Twine &some_twine;
164061da546Spatrick // PyFoo_Bar(x, y, z, NullTerminated(some_twine));
165061da546Spatrick //
166061da546Spatrick // Why a class instead of a function?  If the twine isn't already null
167061da546Spatrick // terminated, it will need a temporary buffer to copy the string
168061da546Spatrick // into.   We need that buffer to stick around for the lifetime of the
169061da546Spatrick // statement.
170061da546Spatrick class NullTerminated {
171061da546Spatrick   const char *str;
172061da546Spatrick   llvm::SmallString<32> storage;
173061da546Spatrick 
174061da546Spatrick public:
175061da546Spatrick   NullTerminated(const llvm::Twine &twine) {
176061da546Spatrick     llvm::StringRef ref = twine.toNullTerminatedStringRef(storage);
177061da546Spatrick     str = ref.begin();
178061da546Spatrick   }
179061da546Spatrick   operator const char *() { return str; }
180061da546Spatrick };
181061da546Spatrick 
182061da546Spatrick inline llvm::Error nullDeref() {
183061da546Spatrick   return llvm::createStringError(llvm::inconvertibleErrorCode(),
184061da546Spatrick                                  "A NULL PyObject* was dereferenced");
185061da546Spatrick }
186061da546Spatrick 
187061da546Spatrick inline llvm::Error exception(const char *s = nullptr) {
188061da546Spatrick   return llvm::make_error<PythonException>(s);
189061da546Spatrick }
190061da546Spatrick 
191061da546Spatrick inline llvm::Error keyError() {
192061da546Spatrick   return llvm::createStringError(llvm::inconvertibleErrorCode(),
193061da546Spatrick                                  "key not in dict");
194061da546Spatrick }
195061da546Spatrick 
196061da546Spatrick #if PY_MAJOR_VERSION < 3
197061da546Spatrick // The python 2 API declares some arguments as char* that should
198061da546Spatrick // be const char *, but it doesn't actually modify them.
199061da546Spatrick inline char *py2_const_cast(const char *s) { return const_cast<char *>(s); }
200061da546Spatrick #else
201061da546Spatrick inline const char *py2_const_cast(const char *s) { return s; }
202061da546Spatrick #endif
203061da546Spatrick 
204061da546Spatrick enum class PyInitialValue { Invalid, Empty };
205061da546Spatrick 
206061da546Spatrick template <typename T, typename Enable = void> struct PythonFormat;
207061da546Spatrick 
208061da546Spatrick template <> struct PythonFormat<unsigned long long> {
209061da546Spatrick   static constexpr char format = 'K';
210061da546Spatrick   static auto get(unsigned long long value) { return value; }
211061da546Spatrick };
212061da546Spatrick 
213061da546Spatrick template <> struct PythonFormat<long long> {
214061da546Spatrick   static constexpr char format = 'L';
215061da546Spatrick   static auto get(long long value) { return value; }
216061da546Spatrick };
217061da546Spatrick 
218061da546Spatrick template <> struct PythonFormat<PyObject *> {
219061da546Spatrick   static constexpr char format = 'O';
220061da546Spatrick   static auto get(PyObject *value) { return value; }
221061da546Spatrick };
222061da546Spatrick 
223061da546Spatrick template <typename T>
224061da546Spatrick struct PythonFormat<
225061da546Spatrick     T, typename std::enable_if<std::is_base_of<PythonObject, T>::value>::type> {
226061da546Spatrick   static constexpr char format = 'O';
227061da546Spatrick   static auto get(const T &value) { return value.get(); }
228061da546Spatrick };
229061da546Spatrick 
230061da546Spatrick class PythonObject {
231061da546Spatrick public:
232*be691f3bSpatrick   PythonObject() = default;
233061da546Spatrick 
234061da546Spatrick   PythonObject(PyRefType type, PyObject *py_obj) {
235061da546Spatrick     m_py_obj = py_obj;
236061da546Spatrick     // If this is a borrowed reference, we need to convert it to
237061da546Spatrick     // an owned reference by incrementing it.  If it is an owned
238061da546Spatrick     // reference (for example the caller allocated it with PyDict_New()
239061da546Spatrick     // then we must *not* increment it.
240061da546Spatrick     if (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed)
241061da546Spatrick       Py_XINCREF(m_py_obj);
242061da546Spatrick   }
243061da546Spatrick 
244061da546Spatrick   PythonObject(const PythonObject &rhs)
245061da546Spatrick       : PythonObject(PyRefType::Borrowed, rhs.m_py_obj) {}
246061da546Spatrick 
247061da546Spatrick   PythonObject(PythonObject &&rhs) {
248061da546Spatrick     m_py_obj = rhs.m_py_obj;
249061da546Spatrick     rhs.m_py_obj = nullptr;
250061da546Spatrick   }
251061da546Spatrick 
252061da546Spatrick   ~PythonObject() { Reset(); }
253061da546Spatrick 
254061da546Spatrick   void Reset() {
255061da546Spatrick     if (m_py_obj && Py_IsInitialized())
256061da546Spatrick       Py_DECREF(m_py_obj);
257061da546Spatrick     m_py_obj = nullptr;
258061da546Spatrick   }
259061da546Spatrick 
260061da546Spatrick   void Dump() const {
261061da546Spatrick     if (m_py_obj)
262061da546Spatrick       _PyObject_Dump(m_py_obj);
263061da546Spatrick     else
264061da546Spatrick       puts("NULL");
265061da546Spatrick   }
266061da546Spatrick 
267061da546Spatrick   void Dump(Stream &strm) const;
268061da546Spatrick 
269061da546Spatrick   PyObject *get() const { return m_py_obj; }
270061da546Spatrick 
271061da546Spatrick   PyObject *release() {
272061da546Spatrick     PyObject *result = m_py_obj;
273061da546Spatrick     m_py_obj = nullptr;
274061da546Spatrick     return result;
275061da546Spatrick   }
276061da546Spatrick 
277061da546Spatrick   PythonObject &operator=(PythonObject other) {
278061da546Spatrick     Reset();
279061da546Spatrick     m_py_obj = std::exchange(other.m_py_obj, nullptr);
280061da546Spatrick     return *this;
281061da546Spatrick   }
282061da546Spatrick 
283061da546Spatrick   PyObjectType GetObjectType() const;
284061da546Spatrick 
285061da546Spatrick   PythonString Repr() const;
286061da546Spatrick 
287061da546Spatrick   PythonString Str() const;
288061da546Spatrick 
289061da546Spatrick   static PythonObject ResolveNameWithDictionary(llvm::StringRef name,
290061da546Spatrick                                                 const PythonDictionary &dict);
291061da546Spatrick 
292061da546Spatrick   template <typename T>
293061da546Spatrick   static T ResolveNameWithDictionary(llvm::StringRef name,
294061da546Spatrick                                      const PythonDictionary &dict) {
295061da546Spatrick     return ResolveNameWithDictionary(name, dict).AsType<T>();
296061da546Spatrick   }
297061da546Spatrick 
298061da546Spatrick   PythonObject ResolveName(llvm::StringRef name) const;
299061da546Spatrick 
300061da546Spatrick   template <typename T> T ResolveName(llvm::StringRef name) const {
301061da546Spatrick     return ResolveName(name).AsType<T>();
302061da546Spatrick   }
303061da546Spatrick 
304061da546Spatrick   bool HasAttribute(llvm::StringRef attribute) const;
305061da546Spatrick 
306061da546Spatrick   PythonObject GetAttributeValue(llvm::StringRef attribute) const;
307061da546Spatrick 
308061da546Spatrick   bool IsNone() const { return m_py_obj == Py_None; }
309061da546Spatrick 
310061da546Spatrick   bool IsValid() const { return m_py_obj != nullptr; }
311061da546Spatrick 
312061da546Spatrick   bool IsAllocated() const { return IsValid() && !IsNone(); }
313061da546Spatrick 
314061da546Spatrick   explicit operator bool() const { return IsValid() && !IsNone(); }
315061da546Spatrick 
316061da546Spatrick   template <typename T> T AsType() const {
317061da546Spatrick     if (!T::Check(m_py_obj))
318061da546Spatrick       return T();
319061da546Spatrick     return T(PyRefType::Borrowed, m_py_obj);
320061da546Spatrick   }
321061da546Spatrick 
322061da546Spatrick   StructuredData::ObjectSP CreateStructuredObject() const;
323061da546Spatrick 
324061da546Spatrick   template <typename... T>
325061da546Spatrick   llvm::Expected<PythonObject> CallMethod(const char *name,
326061da546Spatrick                                           const T &... t) const {
327061da546Spatrick     const char format[] = {'(', PythonFormat<T>::format..., ')', 0};
328061da546Spatrick     PyObject *obj =
329061da546Spatrick         PyObject_CallMethod(m_py_obj, py2_const_cast(name),
330061da546Spatrick                             py2_const_cast(format), PythonFormat<T>::get(t)...);
331061da546Spatrick     if (!obj)
332061da546Spatrick       return exception();
333061da546Spatrick     return python::Take<PythonObject>(obj);
334061da546Spatrick   }
335061da546Spatrick 
336061da546Spatrick   template <typename... T>
337061da546Spatrick   llvm::Expected<PythonObject> Call(const T &... t) const {
338061da546Spatrick     const char format[] = {'(', PythonFormat<T>::format..., ')', 0};
339061da546Spatrick     PyObject *obj = PyObject_CallFunction(m_py_obj, py2_const_cast(format),
340061da546Spatrick                                           PythonFormat<T>::get(t)...);
341061da546Spatrick     if (!obj)
342061da546Spatrick       return exception();
343061da546Spatrick     return python::Take<PythonObject>(obj);
344061da546Spatrick   }
345061da546Spatrick 
346061da546Spatrick   llvm::Expected<PythonObject> GetAttribute(const llvm::Twine &name) const {
347061da546Spatrick     if (!m_py_obj)
348061da546Spatrick       return nullDeref();
349061da546Spatrick     PyObject *obj = PyObject_GetAttrString(m_py_obj, NullTerminated(name));
350061da546Spatrick     if (!obj)
351061da546Spatrick       return exception();
352061da546Spatrick     return python::Take<PythonObject>(obj);
353061da546Spatrick   }
354061da546Spatrick 
355061da546Spatrick   llvm::Expected<bool> IsTrue() {
356061da546Spatrick     if (!m_py_obj)
357061da546Spatrick       return nullDeref();
358061da546Spatrick     int r = PyObject_IsTrue(m_py_obj);
359061da546Spatrick     if (r < 0)
360061da546Spatrick       return exception();
361061da546Spatrick     return !!r;
362061da546Spatrick   }
363061da546Spatrick 
364dda28197Spatrick   llvm::Expected<long long> AsLongLong() const;
365dda28197Spatrick 
366dda28197Spatrick   llvm::Expected<long long> AsUnsignedLongLong() const;
367dda28197Spatrick 
368dda28197Spatrick   // wraps on overflow, instead of raising an error.
369dda28197Spatrick   llvm::Expected<unsigned long long> AsModuloUnsignedLongLong() const;
370061da546Spatrick 
371061da546Spatrick   llvm::Expected<bool> IsInstance(const PythonObject &cls) {
372061da546Spatrick     if (!m_py_obj || !cls.IsValid())
373061da546Spatrick       return nullDeref();
374061da546Spatrick     int r = PyObject_IsInstance(m_py_obj, cls.get());
375061da546Spatrick     if (r < 0)
376061da546Spatrick       return exception();
377061da546Spatrick     return !!r;
378061da546Spatrick   }
379061da546Spatrick 
380061da546Spatrick protected:
381*be691f3bSpatrick   PyObject *m_py_obj = nullptr;
382061da546Spatrick };
383061da546Spatrick 
384061da546Spatrick 
385061da546Spatrick // This is why C++ needs monads.
386061da546Spatrick template <typename T> llvm::Expected<T> As(llvm::Expected<PythonObject> &&obj) {
387061da546Spatrick   if (!obj)
388061da546Spatrick     return obj.takeError();
389061da546Spatrick   if (!T::Check(obj.get().get()))
390061da546Spatrick     return llvm::createStringError(llvm::inconvertibleErrorCode(),
391061da546Spatrick                                    "type error");
392061da546Spatrick   return T(PyRefType::Borrowed, std::move(obj.get().get()));
393061da546Spatrick }
394061da546Spatrick 
395061da546Spatrick template <> llvm::Expected<bool> As<bool>(llvm::Expected<PythonObject> &&obj);
396061da546Spatrick 
397061da546Spatrick template <>
398061da546Spatrick llvm::Expected<long long> As<long long>(llvm::Expected<PythonObject> &&obj);
399061da546Spatrick 
400061da546Spatrick template <>
401dda28197Spatrick llvm::Expected<unsigned long long>
402dda28197Spatrick As<unsigned long long>(llvm::Expected<PythonObject> &&obj);
403dda28197Spatrick 
404dda28197Spatrick template <>
405061da546Spatrick llvm::Expected<std::string> As<std::string>(llvm::Expected<PythonObject> &&obj);
406061da546Spatrick 
407061da546Spatrick 
408061da546Spatrick template <class T> class TypedPythonObject : public PythonObject {
409061da546Spatrick public:
410061da546Spatrick   // override to perform implicit type conversions on Reset
411061da546Spatrick   // This can be eliminated once we drop python 2 support.
412061da546Spatrick   static void Convert(PyRefType &type, PyObject *&py_obj) {}
413061da546Spatrick 
414061da546Spatrick   TypedPythonObject(PyRefType type, PyObject *py_obj) {
415061da546Spatrick     if (!py_obj)
416061da546Spatrick       return;
417061da546Spatrick     T::Convert(type, py_obj);
418061da546Spatrick     if (T::Check(py_obj))
419061da546Spatrick       PythonObject::operator=(PythonObject(type, py_obj));
420061da546Spatrick     else if (type == PyRefType::Owned)
421061da546Spatrick       Py_DECREF(py_obj);
422061da546Spatrick   }
423061da546Spatrick 
424*be691f3bSpatrick   TypedPythonObject() = default;
425061da546Spatrick };
426061da546Spatrick 
427061da546Spatrick class PythonBytes : public TypedPythonObject<PythonBytes> {
428061da546Spatrick public:
429061da546Spatrick   using TypedPythonObject::TypedPythonObject;
430061da546Spatrick   explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes);
431061da546Spatrick   PythonBytes(const uint8_t *bytes, size_t length);
432061da546Spatrick 
433061da546Spatrick   static bool Check(PyObject *py_obj);
434061da546Spatrick 
435061da546Spatrick   llvm::ArrayRef<uint8_t> GetBytes() const;
436061da546Spatrick 
437061da546Spatrick   size_t GetSize() const;
438061da546Spatrick 
439061da546Spatrick   void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
440061da546Spatrick 
441061da546Spatrick   StructuredData::StringSP CreateStructuredString() const;
442061da546Spatrick };
443061da546Spatrick 
444061da546Spatrick class PythonByteArray : public TypedPythonObject<PythonByteArray> {
445061da546Spatrick public:
446061da546Spatrick   using TypedPythonObject::TypedPythonObject;
447061da546Spatrick   explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes);
448061da546Spatrick   PythonByteArray(const uint8_t *bytes, size_t length);
449061da546Spatrick   PythonByteArray(const PythonBytes &object);
450061da546Spatrick 
451061da546Spatrick   static bool Check(PyObject *py_obj);
452061da546Spatrick 
453061da546Spatrick   llvm::ArrayRef<uint8_t> GetBytes() const;
454061da546Spatrick 
455061da546Spatrick   size_t GetSize() const;
456061da546Spatrick 
457061da546Spatrick   void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
458061da546Spatrick 
459061da546Spatrick   StructuredData::StringSP CreateStructuredString() const;
460061da546Spatrick };
461061da546Spatrick 
462061da546Spatrick class PythonString : public TypedPythonObject<PythonString> {
463061da546Spatrick public:
464061da546Spatrick   using TypedPythonObject::TypedPythonObject;
465061da546Spatrick   static llvm::Expected<PythonString> FromUTF8(llvm::StringRef string);
466061da546Spatrick 
467061da546Spatrick   PythonString() : TypedPythonObject() {} // MSVC requires this for some reason
468061da546Spatrick 
469061da546Spatrick   explicit PythonString(llvm::StringRef string); // safe, null on error
470061da546Spatrick 
471061da546Spatrick   static bool Check(PyObject *py_obj);
472061da546Spatrick   static void Convert(PyRefType &type, PyObject *&py_obj);
473061da546Spatrick 
474061da546Spatrick   llvm::StringRef GetString() const; // safe, empty string on error
475061da546Spatrick 
476061da546Spatrick   llvm::Expected<llvm::StringRef> AsUTF8() const;
477061da546Spatrick 
478061da546Spatrick   size_t GetSize() const;
479061da546Spatrick 
480061da546Spatrick   void SetString(llvm::StringRef string); // safe, null on error
481061da546Spatrick 
482061da546Spatrick   StructuredData::StringSP CreateStructuredString() const;
483061da546Spatrick };
484061da546Spatrick 
485061da546Spatrick class PythonInteger : public TypedPythonObject<PythonInteger> {
486061da546Spatrick public:
487061da546Spatrick   using TypedPythonObject::TypedPythonObject;
488061da546Spatrick 
489061da546Spatrick   PythonInteger() : TypedPythonObject() {} // MSVC requires this for some reason
490061da546Spatrick 
491061da546Spatrick   explicit PythonInteger(int64_t value);
492061da546Spatrick 
493061da546Spatrick   static bool Check(PyObject *py_obj);
494061da546Spatrick   static void Convert(PyRefType &type, PyObject *&py_obj);
495061da546Spatrick 
496061da546Spatrick   void SetInteger(int64_t value);
497061da546Spatrick 
498061da546Spatrick   StructuredData::IntegerSP CreateStructuredInteger() const;
499061da546Spatrick };
500061da546Spatrick 
501061da546Spatrick class PythonBoolean : public TypedPythonObject<PythonBoolean> {
502061da546Spatrick public:
503061da546Spatrick   using TypedPythonObject::TypedPythonObject;
504061da546Spatrick 
505061da546Spatrick   explicit PythonBoolean(bool value);
506061da546Spatrick 
507061da546Spatrick   static bool Check(PyObject *py_obj);
508061da546Spatrick 
509061da546Spatrick   bool GetValue() const;
510061da546Spatrick 
511061da546Spatrick   void SetValue(bool value);
512061da546Spatrick 
513061da546Spatrick   StructuredData::BooleanSP CreateStructuredBoolean() const;
514061da546Spatrick };
515061da546Spatrick 
516061da546Spatrick class PythonList : public TypedPythonObject<PythonList> {
517061da546Spatrick public:
518061da546Spatrick   using TypedPythonObject::TypedPythonObject;
519061da546Spatrick 
520061da546Spatrick   PythonList() : TypedPythonObject() {} // MSVC requires this for some reason
521061da546Spatrick 
522061da546Spatrick   explicit PythonList(PyInitialValue value);
523061da546Spatrick   explicit PythonList(int list_size);
524061da546Spatrick 
525061da546Spatrick   static bool Check(PyObject *py_obj);
526061da546Spatrick 
527061da546Spatrick   uint32_t GetSize() const;
528061da546Spatrick 
529061da546Spatrick   PythonObject GetItemAtIndex(uint32_t index) const;
530061da546Spatrick 
531061da546Spatrick   void SetItemAtIndex(uint32_t index, const PythonObject &object);
532061da546Spatrick 
533061da546Spatrick   void AppendItem(const PythonObject &object);
534061da546Spatrick 
535061da546Spatrick   StructuredData::ArraySP CreateStructuredArray() const;
536061da546Spatrick };
537061da546Spatrick 
538061da546Spatrick class PythonTuple : public TypedPythonObject<PythonTuple> {
539061da546Spatrick public:
540061da546Spatrick   using TypedPythonObject::TypedPythonObject;
541061da546Spatrick 
542061da546Spatrick   explicit PythonTuple(PyInitialValue value);
543061da546Spatrick   explicit PythonTuple(int tuple_size);
544061da546Spatrick   PythonTuple(std::initializer_list<PythonObject> objects);
545061da546Spatrick   PythonTuple(std::initializer_list<PyObject *> objects);
546061da546Spatrick 
547061da546Spatrick   static bool Check(PyObject *py_obj);
548061da546Spatrick 
549061da546Spatrick   uint32_t GetSize() const;
550061da546Spatrick 
551061da546Spatrick   PythonObject GetItemAtIndex(uint32_t index) const;
552061da546Spatrick 
553061da546Spatrick   void SetItemAtIndex(uint32_t index, const PythonObject &object);
554061da546Spatrick 
555061da546Spatrick   StructuredData::ArraySP CreateStructuredArray() const;
556061da546Spatrick };
557061da546Spatrick 
558061da546Spatrick class PythonDictionary : public TypedPythonObject<PythonDictionary> {
559061da546Spatrick public:
560061da546Spatrick   using TypedPythonObject::TypedPythonObject;
561061da546Spatrick 
562061da546Spatrick   PythonDictionary() : TypedPythonObject() {} // MSVC requires this for some reason
563061da546Spatrick 
564061da546Spatrick   explicit PythonDictionary(PyInitialValue value);
565061da546Spatrick 
566061da546Spatrick   static bool Check(PyObject *py_obj);
567061da546Spatrick 
568061da546Spatrick   uint32_t GetSize() const;
569061da546Spatrick 
570061da546Spatrick   PythonList GetKeys() const;
571061da546Spatrick 
572061da546Spatrick   PythonObject GetItemForKey(const PythonObject &key) const; // DEPRECATED
573061da546Spatrick   void SetItemForKey(const PythonObject &key,
574061da546Spatrick                      const PythonObject &value); // DEPRECATED
575061da546Spatrick 
576061da546Spatrick   llvm::Expected<PythonObject> GetItem(const PythonObject &key) const;
577061da546Spatrick   llvm::Expected<PythonObject> GetItem(const llvm::Twine &key) const;
578061da546Spatrick   llvm::Error SetItem(const PythonObject &key, const PythonObject &value) const;
579061da546Spatrick   llvm::Error SetItem(const llvm::Twine &key, const PythonObject &value) const;
580061da546Spatrick 
581061da546Spatrick   StructuredData::DictionarySP CreateStructuredDictionary() const;
582061da546Spatrick };
583061da546Spatrick 
584061da546Spatrick class PythonModule : public TypedPythonObject<PythonModule> {
585061da546Spatrick public:
586061da546Spatrick   using TypedPythonObject::TypedPythonObject;
587061da546Spatrick 
588061da546Spatrick   static bool Check(PyObject *py_obj);
589061da546Spatrick 
590061da546Spatrick   static PythonModule BuiltinsModule();
591061da546Spatrick 
592061da546Spatrick   static PythonModule MainModule();
593061da546Spatrick 
594061da546Spatrick   static PythonModule AddModule(llvm::StringRef module);
595061da546Spatrick 
596061da546Spatrick   // safe, returns invalid on error;
597061da546Spatrick   static PythonModule ImportModule(llvm::StringRef name) {
598dda28197Spatrick     std::string s = std::string(name);
599061da546Spatrick     auto mod = Import(s.c_str());
600061da546Spatrick     if (!mod) {
601061da546Spatrick       llvm::consumeError(mod.takeError());
602061da546Spatrick       return PythonModule();
603061da546Spatrick     }
604061da546Spatrick     return std::move(mod.get());
605061da546Spatrick   }
606061da546Spatrick 
607061da546Spatrick   static llvm::Expected<PythonModule> Import(const llvm::Twine &name);
608061da546Spatrick 
609061da546Spatrick   llvm::Expected<PythonObject> Get(const llvm::Twine &name);
610061da546Spatrick 
611061da546Spatrick   PythonDictionary GetDictionary() const;
612061da546Spatrick };
613061da546Spatrick 
614061da546Spatrick class PythonCallable : public TypedPythonObject<PythonCallable> {
615061da546Spatrick public:
616061da546Spatrick   using TypedPythonObject::TypedPythonObject;
617061da546Spatrick 
618061da546Spatrick   struct ArgInfo {
619061da546Spatrick     /* the largest number of positional arguments this callable
620061da546Spatrick      * can accept, or UNBOUNDED, ie UINT_MAX if it's a varargs
621061da546Spatrick      * function and can accept an arbitrary number */
622061da546Spatrick     unsigned max_positional_args;
623061da546Spatrick     static constexpr unsigned UNBOUNDED = UINT_MAX; // FIXME c++17 inline
624061da546Spatrick   };
625061da546Spatrick 
626061da546Spatrick   static bool Check(PyObject *py_obj);
627061da546Spatrick 
628061da546Spatrick   llvm::Expected<ArgInfo> GetArgInfo() const;
629061da546Spatrick 
630061da546Spatrick   PythonObject operator()();
631061da546Spatrick 
632061da546Spatrick   PythonObject operator()(std::initializer_list<PyObject *> args);
633061da546Spatrick 
634061da546Spatrick   PythonObject operator()(std::initializer_list<PythonObject> args);
635061da546Spatrick 
636061da546Spatrick   template <typename Arg, typename... Args>
637061da546Spatrick   PythonObject operator()(const Arg &arg, Args... args) {
638061da546Spatrick     return operator()({arg, args...});
639061da546Spatrick   }
640061da546Spatrick };
641061da546Spatrick 
642061da546Spatrick class PythonFile : public TypedPythonObject<PythonFile> {
643061da546Spatrick public:
644061da546Spatrick   using TypedPythonObject::TypedPythonObject;
645061da546Spatrick 
646061da546Spatrick   PythonFile() : TypedPythonObject() {} // MSVC requires this for some reason
647061da546Spatrick 
648061da546Spatrick   static bool Check(PyObject *py_obj);
649061da546Spatrick 
650061da546Spatrick   static llvm::Expected<PythonFile> FromFile(File &file,
651061da546Spatrick                                              const char *mode = nullptr);
652061da546Spatrick 
653061da546Spatrick   llvm::Expected<lldb::FileSP> ConvertToFile(bool borrowed = false);
654061da546Spatrick   llvm::Expected<lldb::FileSP>
655061da546Spatrick   ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed = false);
656061da546Spatrick };
657061da546Spatrick 
658061da546Spatrick class PythonException : public llvm::ErrorInfo<PythonException> {
659061da546Spatrick private:
660061da546Spatrick   PyObject *m_exception_type, *m_exception, *m_traceback;
661061da546Spatrick   PyObject *m_repr_bytes;
662061da546Spatrick 
663061da546Spatrick public:
664061da546Spatrick   static char ID;
665061da546Spatrick   const char *toCString() const;
666061da546Spatrick   PythonException(const char *caller = nullptr);
667061da546Spatrick   void Restore();
668061da546Spatrick   ~PythonException();
669061da546Spatrick   void log(llvm::raw_ostream &OS) const override;
670061da546Spatrick   std::error_code convertToErrorCode() const override;
671061da546Spatrick   bool Matches(PyObject *exc) const;
672061da546Spatrick   std::string ReadBacktrace() const;
673061da546Spatrick };
674061da546Spatrick 
675061da546Spatrick // This extracts the underlying T out of an Expected<T> and returns it.
676061da546Spatrick // If the Expected is an Error instead of a T, that error will be converted
677061da546Spatrick // into a python exception, and this will return a default-constructed T.
678061da546Spatrick //
679061da546Spatrick // This is appropriate for use right at the boundary of python calling into
680061da546Spatrick // C++, such as in a SWIG typemap.   In such a context you should simply
681061da546Spatrick // check if the returned T is valid, and if it is, return a NULL back
682061da546Spatrick // to python.   This will result in the Error being raised as an exception
683061da546Spatrick // from python code's point of view.
684061da546Spatrick //
685061da546Spatrick // For example:
686061da546Spatrick // ```
687061da546Spatrick // Expected<Foo *> efoop = some_cpp_function();
688061da546Spatrick // Foo *foop = unwrapOrSetPythonException(efoop);
689061da546Spatrick // if (!foop)
690061da546Spatrick //    return NULL;
691061da546Spatrick // do_something(*foop);
692061da546Spatrick //
693061da546Spatrick // If the Error returned was itself created because a python exception was
694061da546Spatrick // raised when C++ code called into python, then the original exception
695061da546Spatrick // will be restored.   Otherwise a simple string exception will be raised.
696061da546Spatrick template <typename T> T unwrapOrSetPythonException(llvm::Expected<T> expected) {
697061da546Spatrick   if (expected)
698061da546Spatrick     return expected.get();
699061da546Spatrick   llvm::handleAllErrors(
700061da546Spatrick       expected.takeError(), [](PythonException &E) { E.Restore(); },
701061da546Spatrick       [](const llvm::ErrorInfoBase &E) {
702061da546Spatrick         PyErr_SetString(PyExc_Exception, E.message().c_str());
703061da546Spatrick       });
704061da546Spatrick   return T();
705061da546Spatrick }
706061da546Spatrick 
707061da546Spatrick // This is only here to help incrementally migrate old, exception-unsafe
708061da546Spatrick // code.
709061da546Spatrick template <typename T> T unwrapIgnoringErrors(llvm::Expected<T> expected) {
710061da546Spatrick   if (expected)
711061da546Spatrick     return std::move(expected.get());
712061da546Spatrick   llvm::consumeError(expected.takeError());
713061da546Spatrick   return T();
714061da546Spatrick }
715061da546Spatrick 
716061da546Spatrick llvm::Expected<PythonObject> runStringOneLine(const llvm::Twine &string,
717061da546Spatrick                                               const PythonDictionary &globals,
718061da546Spatrick                                               const PythonDictionary &locals);
719061da546Spatrick 
720061da546Spatrick llvm::Expected<PythonObject> runStringMultiLine(const llvm::Twine &string,
721061da546Spatrick                                                 const PythonDictionary &globals,
722061da546Spatrick                                                 const PythonDictionary &locals);
723061da546Spatrick 
724061da546Spatrick // Sometimes the best way to interact with a python interpreter is
725061da546Spatrick // to run some python code.   You construct a PythonScript with
726061da546Spatrick // script string.   The script assigns some function to `_function_`
727061da546Spatrick // and you get a C++ callable object that calls the python function.
728061da546Spatrick //
729061da546Spatrick // Example:
730061da546Spatrick //
731061da546Spatrick // const char script[] = R"(
732061da546Spatrick // def main(x, y):
733061da546Spatrick //    ....
734061da546Spatrick // )";
735061da546Spatrick //
736061da546Spatrick // Expected<PythonObject> cpp_foo_wrapper(PythonObject x, PythonObject y) {
737061da546Spatrick //   // no need to synchronize access to this global, we already have the GIL
738061da546Spatrick //   static PythonScript foo(script)
739061da546Spatrick //   return  foo(x, y);
740061da546Spatrick // }
741061da546Spatrick class PythonScript {
742061da546Spatrick   const char *script;
743061da546Spatrick   PythonCallable function;
744061da546Spatrick 
745061da546Spatrick   llvm::Error Init();
746061da546Spatrick 
747061da546Spatrick public:
748061da546Spatrick   PythonScript(const char *script) : script(script), function() {}
749061da546Spatrick 
750061da546Spatrick   template <typename... Args>
751061da546Spatrick   llvm::Expected<PythonObject> operator()(Args &&... args) {
752061da546Spatrick     if (llvm::Error error = Init())
753061da546Spatrick       return std::move(error);
754061da546Spatrick     return function.Call(std::forward<Args>(args)...);
755061da546Spatrick   }
756061da546Spatrick };
757061da546Spatrick 
758061da546Spatrick } // namespace python
759061da546Spatrick } // namespace lldb_private
760061da546Spatrick 
761061da546Spatrick #endif
762061da546Spatrick 
763061da546Spatrick #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
764