1edb35d95SEugene Zelenko //===-- PythonDataObjects.h--------------------------------------*- C++ -*-===//
22c1f46dcSZachary Turner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62c1f46dcSZachary Turner //
72c1f46dcSZachary Turner //===----------------------------------------------------------------------===//
82c1f46dcSZachary Turner 
9085328eeSLawrence D'Anna //
10085328eeSLawrence D'Anna // !! FIXME FIXME FIXME !!
11085328eeSLawrence D'Anna //
12085328eeSLawrence D'Anna // Python APIs nearly all can return an exception.   They do this
13085328eeSLawrence D'Anna // by returning NULL, or -1, or some such value and setting
14085328eeSLawrence D'Anna // the exception state with PyErr_Set*().   Exceptions must be
15085328eeSLawrence D'Anna // handled before further python API functions are called.   Failure
16085328eeSLawrence D'Anna // to do so will result in asserts on debug builds of python.
17085328eeSLawrence D'Anna // It will also sometimes, but not usually result in crashes of
18085328eeSLawrence D'Anna // release builds.
19085328eeSLawrence D'Anna //
20085328eeSLawrence D'Anna // Nearly all the code in this header does not handle python exceptions
21085328eeSLawrence D'Anna // correctly.  It should all be converted to return Expected<> or
22085328eeSLawrence D'Anna // Error types to capture the exception.
23085328eeSLawrence D'Anna //
24085328eeSLawrence D'Anna // Everything in this file except functions that return Error or
25085328eeSLawrence D'Anna // Expected<> is considered deprecated and should not be
26085328eeSLawrence D'Anna // used in new code.  If you need to use it, fix it first.
27085328eeSLawrence D'Anna //
28d3bd5b3dSLawrence D'Anna //
29d3bd5b3dSLawrence D'Anna // TODOs for this file
30d3bd5b3dSLawrence D'Anna //
31d3bd5b3dSLawrence D'Anna // * Make all methods safe for exceptions.
32d3bd5b3dSLawrence D'Anna //
33d3bd5b3dSLawrence D'Anna // * Eliminate method signatures that must translate exceptions into
34d3bd5b3dSLawrence D'Anna //   empty objects or NULLs.   Almost everything here should return
35d3bd5b3dSLawrence D'Anna //   Expected<>.   It should be acceptable for certain operations that
36d3bd5b3dSLawrence D'Anna //   can never fail to assert instead, such as the creation of
37d3bd5b3dSLawrence D'Anna //   PythonString from a string literal.
38d3bd5b3dSLawrence D'Anna //
39e9264b74SKazuaki Ishizaki // * Eliminate Reset(), and make all non-default constructors private.
40d3bd5b3dSLawrence D'Anna //   Python objects should be created with Retain<> or Take<>, and they
41d3bd5b3dSLawrence D'Anna //   should be assigned with operator=
42d3bd5b3dSLawrence D'Anna //
43d3bd5b3dSLawrence D'Anna // * Eliminate default constructors, make python objects always
44d3bd5b3dSLawrence D'Anna //   nonnull, and use optionals where necessary.
45d3bd5b3dSLawrence D'Anna //
46d3bd5b3dSLawrence D'Anna 
47085328eeSLawrence D'Anna 
482c1f46dcSZachary Turner #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
492c1f46dcSZachary Turner #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
502c1f46dcSZachary Turner 
5159998b7bSJonas Devlieghere #include "lldb/Host/Config.h"
5259998b7bSJonas Devlieghere 
534e26cf2cSJonas Devlieghere #if LLDB_ENABLE_PYTHON
54d68983e3SPavel Labath 
5541de9a97SKate Stone // LLDB Python header must be included first
5641de9a97SKate Stone #include "lldb-python.h"
5741de9a97SKate Stone 
589c40264fSZachary Turner #include "lldb/Host/File.h"
59f2a8bccfSPavel Labath #include "lldb/Utility/StructuredData.h"
602c1f46dcSZachary Turner 
615a72c02bSZachary Turner #include "llvm/ADT/ArrayRef.h"
625a72c02bSZachary Turner 
632c1f46dcSZachary Turner namespace lldb_private {
6404edd189SLawrence D'Anna namespace python {
65edb35d95SEugene Zelenko 
66085328eeSLawrence D'Anna class PythonObject;
675a72c02bSZachary Turner class PythonBytes;
682c1f46dcSZachary Turner class PythonString;
692c1f46dcSZachary Turner class PythonList;
702c1f46dcSZachary Turner class PythonDictionary;
712c1f46dcSZachary Turner class PythonInteger;
72085328eeSLawrence D'Anna class PythonException;
732c1f46dcSZachary Turner 
74b9c1b51eSKate Stone class StructuredPythonObject : public StructuredData::Generic {
752c1f46dcSZachary Turner public:
76b9c1b51eSKate Stone   StructuredPythonObject() : StructuredData::Generic() {}
772c1f46dcSZachary Turner 
78b9c1b51eSKate Stone   StructuredPythonObject(void *obj) : StructuredData::Generic(obj) {
792c1f46dcSZachary Turner     Py_XINCREF(GetValue());
802c1f46dcSZachary Turner   }
812c1f46dcSZachary Turner 
82b9c1b51eSKate Stone   ~StructuredPythonObject() override {
832c1f46dcSZachary Turner     if (Py_IsInitialized())
842c1f46dcSZachary Turner       Py_XDECREF(GetValue());
852c1f46dcSZachary Turner     SetValue(nullptr);
862c1f46dcSZachary Turner   }
872c1f46dcSZachary Turner 
88b9c1b51eSKate Stone   bool IsValid() const override { return GetValue() && GetValue() != Py_None; }
892c1f46dcSZachary Turner 
902783d817SJonas Devlieghere   void Serialize(llvm::json::OStream &s) const override;
912c1f46dcSZachary Turner 
922c1f46dcSZachary Turner private:
93*eaebcbc6SKonrad Kleine   StructuredPythonObject(const StructuredPythonObject &) = delete;
94*eaebcbc6SKonrad Kleine   const StructuredPythonObject &
95*eaebcbc6SKonrad Kleine   operator=(const StructuredPythonObject &) = delete;
962c1f46dcSZachary Turner };
972c1f46dcSZachary Turner 
98b9c1b51eSKate Stone enum class PyObjectType {
992c1f46dcSZachary Turner   Unknown,
1002c1f46dcSZachary Turner   None,
101b81d715cSTatyana Krasnukha   Boolean,
1022c1f46dcSZachary Turner   Integer,
1032c1f46dcSZachary Turner   Dictionary,
1042c1f46dcSZachary Turner   List,
1059c40264fSZachary Turner   String,
1065a72c02bSZachary Turner   Bytes,
107f9d6d204SZachary Turner   ByteArray,
1087841efbbSZachary Turner   Module,
109a1405147SZachary Turner   Callable,
110a1405147SZachary Turner   Tuple,
1119c40264fSZachary Turner   File
1122c1f46dcSZachary Turner };
1132c1f46dcSZachary Turner 
114b9c1b51eSKate Stone enum class PyRefType {
115f8b22f8fSZachary Turner   Borrowed, // We are not given ownership of the incoming PyObject.
116f8b22f8fSZachary Turner             // We cannot safely hold it without calling Py_INCREF.
117f8b22f8fSZachary Turner   Owned     // We have ownership of the incoming PyObject.  We should
118f8b22f8fSZachary Turner             // not call Py_INCREF.
119f8b22f8fSZachary Turner };
120f8b22f8fSZachary Turner 
121085328eeSLawrence D'Anna 
122085328eeSLawrence D'Anna // Take a reference that you already own, and turn it into
123085328eeSLawrence D'Anna // a PythonObject.
124085328eeSLawrence D'Anna //
125085328eeSLawrence D'Anna // Most python API methods will return a +1 reference
126085328eeSLawrence D'Anna // if they succeed or NULL if and only if
127085328eeSLawrence D'Anna // they set an exception.   Use this to collect such return
128085328eeSLawrence D'Anna // values, after checking for NULL.
129085328eeSLawrence D'Anna //
130085328eeSLawrence D'Anna // If T is not just PythonObject, then obj must be already be
131085328eeSLawrence D'Anna // checked to be of the correct type.
132085328eeSLawrence D'Anna template <typename T> T Take(PyObject *obj) {
133085328eeSLawrence D'Anna   assert(obj);
134085328eeSLawrence D'Anna   assert(!PyErr_Occurred());
135085328eeSLawrence D'Anna   T thing(PyRefType::Owned, obj);
136085328eeSLawrence D'Anna   assert(thing.IsValid());
1371dfb1a85SPavel Labath   return thing;
138085328eeSLawrence D'Anna }
139085328eeSLawrence D'Anna 
140085328eeSLawrence D'Anna // Retain a reference you have borrowed, and turn it into
141085328eeSLawrence D'Anna // a PythonObject.
142085328eeSLawrence D'Anna //
143085328eeSLawrence D'Anna // A minority of python APIs return a borrowed reference
144085328eeSLawrence D'Anna // instead of a +1.   They will also return NULL if and only
145085328eeSLawrence D'Anna // if they set an exception.   Use this to collect such return
146085328eeSLawrence D'Anna // values, after checking for NULL.
147085328eeSLawrence D'Anna //
148085328eeSLawrence D'Anna // If T is not just PythonObject, then obj must be already be
149085328eeSLawrence D'Anna // checked to be of the correct type.
150085328eeSLawrence D'Anna template <typename T> T Retain(PyObject *obj) {
151085328eeSLawrence D'Anna   assert(obj);
152085328eeSLawrence D'Anna   assert(!PyErr_Occurred());
153085328eeSLawrence D'Anna   T thing(PyRefType::Borrowed, obj);
154085328eeSLawrence D'Anna   assert(thing.IsValid());
1551dfb1a85SPavel Labath   return thing;
156085328eeSLawrence D'Anna }
157085328eeSLawrence D'Anna 
158722b6189SLawrence D'Anna // This class can be used like a utility function to convert from
159722b6189SLawrence D'Anna // a llvm-friendly Twine into a null-terminated const char *,
160722b6189SLawrence D'Anna // which is the form python C APIs want their strings in.
161722b6189SLawrence D'Anna //
162722b6189SLawrence D'Anna // Example:
163722b6189SLawrence D'Anna // const llvm::Twine &some_twine;
164722b6189SLawrence D'Anna // PyFoo_Bar(x, y, z, NullTerminated(some_twine));
165722b6189SLawrence D'Anna //
166722b6189SLawrence D'Anna // Why a class instead of a function?  If the twine isn't already null
167722b6189SLawrence D'Anna // terminated, it will need a temporary buffer to copy the string
168722b6189SLawrence D'Anna // into.   We need that buffer to stick around for the lifetime of the
169722b6189SLawrence D'Anna // statement.
170722b6189SLawrence D'Anna class NullTerminated {
171722b6189SLawrence D'Anna   const char *str;
172722b6189SLawrence D'Anna   llvm::SmallString<32> storage;
173722b6189SLawrence D'Anna 
174722b6189SLawrence D'Anna public:
175722b6189SLawrence D'Anna   NullTerminated(const llvm::Twine &twine) {
176722b6189SLawrence D'Anna     llvm::StringRef ref = twine.toNullTerminatedStringRef(storage);
177722b6189SLawrence D'Anna     str = ref.begin();
178722b6189SLawrence D'Anna   }
179722b6189SLawrence D'Anna   operator const char *() { return str; }
180722b6189SLawrence D'Anna };
181722b6189SLawrence D'Anna 
18204edd189SLawrence D'Anna inline llvm::Error nullDeref() {
18304edd189SLawrence D'Anna   return llvm::createStringError(llvm::inconvertibleErrorCode(),
18404edd189SLawrence D'Anna                                  "A NULL PyObject* was dereferenced");
18504edd189SLawrence D'Anna }
18604edd189SLawrence D'Anna 
18704edd189SLawrence D'Anna inline llvm::Error exception(const char *s = nullptr) {
18804edd189SLawrence D'Anna   return llvm::make_error<PythonException>(s);
18904edd189SLawrence D'Anna }
19004edd189SLawrence D'Anna 
19104edd189SLawrence D'Anna inline llvm::Error keyError() {
19204edd189SLawrence D'Anna   return llvm::createStringError(llvm::inconvertibleErrorCode(),
19304edd189SLawrence D'Anna                                  "key not in dict");
19404edd189SLawrence D'Anna }
195085328eeSLawrence D'Anna 
1966a93a12aSLawrence D'Anna #if PY_MAJOR_VERSION < 3
1976a93a12aSLawrence D'Anna // The python 2 API declares some arguments as char* that should
1986a93a12aSLawrence D'Anna // be const char *, but it doesn't actually modify them.
1996a93a12aSLawrence D'Anna inline char *py2_const_cast(const char *s) { return const_cast<char *>(s); }
2006a93a12aSLawrence D'Anna #else
2016a93a12aSLawrence D'Anna inline const char *py2_const_cast(const char *s) { return s; }
2026a93a12aSLawrence D'Anna #endif
2036a93a12aSLawrence D'Anna 
204b9c1b51eSKate Stone enum class PyInitialValue { Invalid, Empty };
205f8b22f8fSZachary Turner 
206085328eeSLawrence D'Anna template <typename T, typename Enable = void> struct PythonFormat;
207085328eeSLawrence D'Anna 
208085328eeSLawrence D'Anna template <> struct PythonFormat<unsigned long long> {
209085328eeSLawrence D'Anna   static constexpr char format = 'K';
210085328eeSLawrence D'Anna   static auto get(unsigned long long value) { return value; }
211085328eeSLawrence D'Anna };
212085328eeSLawrence D'Anna 
213085328eeSLawrence D'Anna template <> struct PythonFormat<long long> {
214085328eeSLawrence D'Anna   static constexpr char format = 'L';
215085328eeSLawrence D'Anna   static auto get(long long value) { return value; }
216085328eeSLawrence D'Anna };
217085328eeSLawrence D'Anna 
21804edd189SLawrence D'Anna template <> struct PythonFormat<PyObject *> {
21904edd189SLawrence D'Anna   static constexpr char format = 'O';
22004edd189SLawrence D'Anna   static auto get(PyObject *value) { return value; }
22104edd189SLawrence D'Anna };
22204edd189SLawrence D'Anna 
223085328eeSLawrence D'Anna template <typename T>
224085328eeSLawrence D'Anna struct PythonFormat<
225085328eeSLawrence D'Anna     T, typename std::enable_if<std::is_base_of<PythonObject, T>::value>::type> {
226085328eeSLawrence D'Anna   static constexpr char format = 'O';
227085328eeSLawrence D'Anna   static auto get(const T &value) { return value.get(); }
228085328eeSLawrence D'Anna };
229085328eeSLawrence D'Anna 
230b9c1b51eSKate Stone class PythonObject {
2312c1f46dcSZachary Turner public:
232b9c1b51eSKate Stone   PythonObject() : m_py_obj(nullptr) {}
2332c1f46dcSZachary Turner 
23404edd189SLawrence D'Anna   PythonObject(PyRefType type, PyObject *py_obj) {
23504edd189SLawrence D'Anna     m_py_obj = py_obj;
23604edd189SLawrence D'Anna     // If this is a borrowed reference, we need to convert it to
23704edd189SLawrence D'Anna     // an owned reference by incrementing it.  If it is an owned
23804edd189SLawrence D'Anna     // reference (for example the caller allocated it with PyDict_New()
23904edd189SLawrence D'Anna     // then we must *not* increment it.
24004edd189SLawrence D'Anna     if (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed)
24104edd189SLawrence D'Anna       Py_XINCREF(m_py_obj);
2422c1f46dcSZachary Turner   }
2432c1f46dcSZachary Turner 
24403819d1cSLawrence D'Anna   PythonObject(const PythonObject &rhs)
24503819d1cSLawrence D'Anna       : PythonObject(PyRefType::Borrowed, rhs.m_py_obj) {}
2462c1f46dcSZachary Turner 
247085328eeSLawrence D'Anna   PythonObject(PythonObject &&rhs) {
248085328eeSLawrence D'Anna     m_py_obj = rhs.m_py_obj;
249085328eeSLawrence D'Anna     rhs.m_py_obj = nullptr;
250085328eeSLawrence D'Anna   }
251085328eeSLawrence D'Anna 
252d3bd5b3dSLawrence D'Anna   ~PythonObject() { Reset(); }
2532c1f46dcSZachary Turner 
254b9c1b51eSKate Stone   void Reset() {
255085328eeSLawrence D'Anna     if (m_py_obj && Py_IsInitialized())
256085328eeSLawrence D'Anna       Py_DECREF(m_py_obj);
257f8b22f8fSZachary Turner     m_py_obj = nullptr;
2582c1f46dcSZachary Turner   }
259f8b22f8fSZachary Turner 
260b9c1b51eSKate Stone   void Dump() const {
2612c1f46dcSZachary Turner     if (m_py_obj)
2622c1f46dcSZachary Turner       _PyObject_Dump(m_py_obj);
2632c1f46dcSZachary Turner     else
2642c1f46dcSZachary Turner       puts("NULL");
2652c1f46dcSZachary Turner   }
2662c1f46dcSZachary Turner 
267b9c1b51eSKate Stone   void Dump(Stream &strm) const;
2682c1f46dcSZachary Turner 
269b9c1b51eSKate Stone   PyObject *get() const { return m_py_obj; }
2702c1f46dcSZachary Turner 
271b9c1b51eSKate Stone   PyObject *release() {
27260c24f70SZachary Turner     PyObject *result = m_py_obj;
27360c24f70SZachary Turner     m_py_obj = nullptr;
27460c24f70SZachary Turner     return result;
27560c24f70SZachary Turner   }
27660c24f70SZachary Turner 
27703819d1cSLawrence D'Anna   PythonObject &operator=(PythonObject other) {
278085328eeSLawrence D'Anna     Reset();
27903819d1cSLawrence D'Anna     m_py_obj = std::exchange(other.m_py_obj, nullptr);
280085328eeSLawrence D'Anna     return *this;
281085328eeSLawrence D'Anna   }
282085328eeSLawrence D'Anna 
283b9c1b51eSKate Stone   PyObjectType GetObjectType() const;
2847841efbbSZachary Turner 
285b9c1b51eSKate Stone   PythonString Repr() const;
2867841efbbSZachary Turner 
287b9c1b51eSKate Stone   PythonString Str() const;
2887841efbbSZachary Turner 
289b9c1b51eSKate Stone   static PythonObject ResolveNameWithDictionary(llvm::StringRef name,
290b9c1b51eSKate Stone                                                 const PythonDictionary &dict);
2917841efbbSZachary Turner 
292b58fb2f4SZachary Turner   template <typename T>
293b9c1b51eSKate Stone   static T ResolveNameWithDictionary(llvm::StringRef name,
294b9c1b51eSKate Stone                                      const PythonDictionary &dict) {
295b58fb2f4SZachary Turner     return ResolveNameWithDictionary(name, dict).AsType<T>();
296b58fb2f4SZachary Turner   }
297b58fb2f4SZachary Turner 
298b9c1b51eSKate Stone   PythonObject ResolveName(llvm::StringRef name) const;
2997841efbbSZachary Turner 
300b9c1b51eSKate Stone   template <typename T> T ResolveName(llvm::StringRef name) const {
301b58fb2f4SZachary Turner     return ResolveName(name).AsType<T>();
302b58fb2f4SZachary Turner   }
303b58fb2f4SZachary Turner 
304b9c1b51eSKate Stone   bool HasAttribute(llvm::StringRef attribute) const;
3059c40264fSZachary Turner 
306b9c1b51eSKate Stone   PythonObject GetAttributeValue(llvm::StringRef attribute) const;
3077d6d218eSZachary Turner 
308085328eeSLawrence D'Anna   bool IsNone() const { return m_py_obj == Py_None; }
309f8b22f8fSZachary Turner 
310085328eeSLawrence D'Anna   bool IsValid() const { return m_py_obj != nullptr; }
311f8b22f8fSZachary Turner 
312085328eeSLawrence D'Anna   bool IsAllocated() const { return IsValid() && !IsNone(); }
313085328eeSLawrence D'Anna 
314085328eeSLawrence D'Anna   explicit operator bool() const { return IsValid() && !IsNone(); }
3152c1f46dcSZachary Turner 
316b9c1b51eSKate Stone   template <typename T> T AsType() const {
3177d6d218eSZachary Turner     if (!T::Check(m_py_obj))
3187d6d218eSZachary Turner       return T();
3197d6d218eSZachary Turner     return T(PyRefType::Borrowed, m_py_obj);
3207d6d218eSZachary Turner   }
3217d6d218eSZachary Turner 
322b9c1b51eSKate Stone   StructuredData::ObjectSP CreateStructuredObject() const;
3232c1f46dcSZachary Turner 
324085328eeSLawrence D'Anna public:
325085328eeSLawrence D'Anna   template <typename... T>
326085328eeSLawrence D'Anna   llvm::Expected<PythonObject> CallMethod(const char *name,
327085328eeSLawrence D'Anna                                           const T &... t) const {
328085328eeSLawrence D'Anna     const char format[] = {'(', PythonFormat<T>::format..., ')', 0};
329085328eeSLawrence D'Anna     PyObject *obj =
330c86a6acaSLawrence D'Anna         PyObject_CallMethod(m_py_obj, py2_const_cast(name),
331c86a6acaSLawrence D'Anna                             py2_const_cast(format), PythonFormat<T>::get(t)...);
332c86a6acaSLawrence D'Anna     if (!obj)
333c86a6acaSLawrence D'Anna       return exception();
334c86a6acaSLawrence D'Anna     return python::Take<PythonObject>(obj);
335c86a6acaSLawrence D'Anna   }
336c86a6acaSLawrence D'Anna 
337c86a6acaSLawrence D'Anna   template <typename... T>
338c86a6acaSLawrence D'Anna   llvm::Expected<PythonObject> Call(const T &... t) const {
339c86a6acaSLawrence D'Anna     const char format[] = {'(', PythonFormat<T>::format..., ')', 0};
340c86a6acaSLawrence D'Anna     PyObject *obj = PyObject_CallFunction(m_py_obj, py2_const_cast(format),
341c86a6acaSLawrence D'Anna                                           PythonFormat<T>::get(t)...);
342085328eeSLawrence D'Anna     if (!obj)
343085328eeSLawrence D'Anna       return exception();
344085328eeSLawrence D'Anna     return python::Take<PythonObject>(obj);
345085328eeSLawrence D'Anna   }
346085328eeSLawrence D'Anna 
347722b6189SLawrence D'Anna   llvm::Expected<PythonObject> GetAttribute(const llvm::Twine &name) const {
348085328eeSLawrence D'Anna     if (!m_py_obj)
349085328eeSLawrence D'Anna       return nullDeref();
350722b6189SLawrence D'Anna     PyObject *obj = PyObject_GetAttrString(m_py_obj, NullTerminated(name));
351085328eeSLawrence D'Anna     if (!obj)
352085328eeSLawrence D'Anna       return exception();
353085328eeSLawrence D'Anna     return python::Take<PythonObject>(obj);
354085328eeSLawrence D'Anna   }
355085328eeSLawrence D'Anna 
356085328eeSLawrence D'Anna   llvm::Expected<bool> IsTrue() {
357085328eeSLawrence D'Anna     if (!m_py_obj)
358085328eeSLawrence D'Anna       return nullDeref();
359085328eeSLawrence D'Anna     int r = PyObject_IsTrue(m_py_obj);
360085328eeSLawrence D'Anna     if (r < 0)
361085328eeSLawrence D'Anna       return exception();
362085328eeSLawrence D'Anna     return !!r;
363085328eeSLawrence D'Anna   }
364085328eeSLawrence D'Anna 
36552712d3fSLawrence D'Anna   llvm::Expected<long long> AsLongLong() const;
36652712d3fSLawrence D'Anna 
36752712d3fSLawrence D'Anna   llvm::Expected<long long> AsUnsignedLongLong() const;
36852712d3fSLawrence D'Anna 
36952712d3fSLawrence D'Anna   // wraps on overflow, instead of raising an error.
37052712d3fSLawrence D'Anna   llvm::Expected<unsigned long long> AsModuloUnsignedLongLong() const;
371085328eeSLawrence D'Anna 
372085328eeSLawrence D'Anna   llvm::Expected<bool> IsInstance(const PythonObject &cls) {
373085328eeSLawrence D'Anna     if (!m_py_obj || !cls.IsValid())
374085328eeSLawrence D'Anna       return nullDeref();
375085328eeSLawrence D'Anna     int r = PyObject_IsInstance(m_py_obj, cls.get());
376085328eeSLawrence D'Anna     if (r < 0)
377085328eeSLawrence D'Anna       return exception();
378085328eeSLawrence D'Anna     return !!r;
379085328eeSLawrence D'Anna   }
380085328eeSLawrence D'Anna 
381085328eeSLawrence D'Anna protected:
3822c1f46dcSZachary Turner   PyObject *m_py_obj;
3832c1f46dcSZachary Turner };
3842c1f46dcSZachary Turner 
385085328eeSLawrence D'Anna 
386085328eeSLawrence D'Anna // This is why C++ needs monads.
387085328eeSLawrence D'Anna template <typename T> llvm::Expected<T> As(llvm::Expected<PythonObject> &&obj) {
388085328eeSLawrence D'Anna   if (!obj)
389085328eeSLawrence D'Anna     return obj.takeError();
390085328eeSLawrence D'Anna   if (!T::Check(obj.get().get()))
391085328eeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
392085328eeSLawrence D'Anna                                    "type error");
393085328eeSLawrence D'Anna   return T(PyRefType::Borrowed, std::move(obj.get().get()));
394085328eeSLawrence D'Anna }
395085328eeSLawrence D'Anna 
396085328eeSLawrence D'Anna template <> llvm::Expected<bool> As<bool>(llvm::Expected<PythonObject> &&obj);
397085328eeSLawrence D'Anna 
398085328eeSLawrence D'Anna template <>
399085328eeSLawrence D'Anna llvm::Expected<long long> As<long long>(llvm::Expected<PythonObject> &&obj);
400085328eeSLawrence D'Anna 
401c86a6acaSLawrence D'Anna template <>
40252712d3fSLawrence D'Anna llvm::Expected<unsigned long long>
40352712d3fSLawrence D'Anna As<unsigned long long>(llvm::Expected<PythonObject> &&obj);
40452712d3fSLawrence D'Anna 
40552712d3fSLawrence D'Anna template <>
406c86a6acaSLawrence D'Anna llvm::Expected<std::string> As<std::string>(llvm::Expected<PythonObject> &&obj);
407c86a6acaSLawrence D'Anna 
408085328eeSLawrence D'Anna 
409d3bd5b3dSLawrence D'Anna template <class T> class TypedPythonObject : public PythonObject {
4105a72c02bSZachary Turner public:
411d3bd5b3dSLawrence D'Anna   // override to perform implicit type conversions on Reset
412d3bd5b3dSLawrence D'Anna   // This can be eliminated once we drop python 2 support.
413d3bd5b3dSLawrence D'Anna   static void Convert(PyRefType &type, PyObject *&py_obj) {}
414d3bd5b3dSLawrence D'Anna 
415722b6189SLawrence D'Anna   TypedPythonObject(PyRefType type, PyObject *py_obj) {
416d3bd5b3dSLawrence D'Anna     if (!py_obj)
417d3bd5b3dSLawrence D'Anna       return;
418d3bd5b3dSLawrence D'Anna     T::Convert(type, py_obj);
419d3bd5b3dSLawrence D'Anna     if (T::Check(py_obj))
42004edd189SLawrence D'Anna       PythonObject::operator=(PythonObject(type, py_obj));
421d3bd5b3dSLawrence D'Anna     else if (type == PyRefType::Owned)
422d3bd5b3dSLawrence D'Anna       Py_DECREF(py_obj);
423d3bd5b3dSLawrence D'Anna   }
424d3bd5b3dSLawrence D'Anna 
425d3bd5b3dSLawrence D'Anna   TypedPythonObject() {}
426d3bd5b3dSLawrence D'Anna };
427d3bd5b3dSLawrence D'Anna 
428d3bd5b3dSLawrence D'Anna class PythonBytes : public TypedPythonObject<PythonBytes> {
429d3bd5b3dSLawrence D'Anna public:
430d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
4315a72c02bSZachary Turner   explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes);
4325a72c02bSZachary Turner   PythonBytes(const uint8_t *bytes, size_t length);
4335a72c02bSZachary Turner 
434b9c1b51eSKate Stone   static bool Check(PyObject *py_obj);
4355a72c02bSZachary Turner 
436b9c1b51eSKate Stone   llvm::ArrayRef<uint8_t> GetBytes() const;
4375a72c02bSZachary Turner 
438b9c1b51eSKate Stone   size_t GetSize() const;
4395a72c02bSZachary Turner 
440b9c1b51eSKate Stone   void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
4415a72c02bSZachary Turner 
442b9c1b51eSKate Stone   StructuredData::StringSP CreateStructuredString() const;
4435a72c02bSZachary Turner };
4445a72c02bSZachary Turner 
445d3bd5b3dSLawrence D'Anna class PythonByteArray : public TypedPythonObject<PythonByteArray> {
446f9d6d204SZachary Turner public:
447d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
448f9d6d204SZachary Turner   explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes);
449f9d6d204SZachary Turner   PythonByteArray(const uint8_t *bytes, size_t length);
450f9d6d204SZachary Turner   PythonByteArray(const PythonBytes &object);
451f9d6d204SZachary Turner 
452b9c1b51eSKate Stone   static bool Check(PyObject *py_obj);
453f9d6d204SZachary Turner 
454b9c1b51eSKate Stone   llvm::ArrayRef<uint8_t> GetBytes() const;
455f9d6d204SZachary Turner 
456b9c1b51eSKate Stone   size_t GetSize() const;
457f9d6d204SZachary Turner 
458b9c1b51eSKate Stone   void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
459f9d6d204SZachary Turner 
460b9c1b51eSKate Stone   StructuredData::StringSP CreateStructuredString() const;
461f9d6d204SZachary Turner };
462f9d6d204SZachary Turner 
463d3bd5b3dSLawrence D'Anna class PythonString : public TypedPythonObject<PythonString> {
4642c1f46dcSZachary Turner public:
465d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
466085328eeSLawrence D'Anna   static llvm::Expected<PythonString> FromUTF8(llvm::StringRef string);
467085328eeSLawrence D'Anna 
468d3bd5b3dSLawrence D'Anna   PythonString() : TypedPythonObject() {} // MSVC requires this for some reason
469edb35d95SEugene Zelenko 
470d3bd5b3dSLawrence D'Anna   explicit PythonString(llvm::StringRef string); // safe, null on error
4712c1f46dcSZachary Turner 
47222c8efcdSZachary Turner   static bool Check(PyObject *py_obj);
473d3bd5b3dSLawrence D'Anna   static void Convert(PyRefType &type, PyObject *&py_obj);
4742c1f46dcSZachary Turner 
475085328eeSLawrence D'Anna   llvm::StringRef GetString() const; // safe, empty string on error
476085328eeSLawrence D'Anna 
477085328eeSLawrence D'Anna   llvm::Expected<llvm::StringRef> AsUTF8() const;
4782c1f46dcSZachary Turner 
479b9c1b51eSKate Stone   size_t GetSize() const;
4802c1f46dcSZachary Turner 
481085328eeSLawrence D'Anna   void SetString(llvm::StringRef string); // safe, null on error
4822c1f46dcSZachary Turner 
4832c1f46dcSZachary Turner   StructuredData::StringSP CreateStructuredString() const;
4842c1f46dcSZachary Turner };
4852c1f46dcSZachary Turner 
486d3bd5b3dSLawrence D'Anna class PythonInteger : public TypedPythonObject<PythonInteger> {
4872c1f46dcSZachary Turner public:
488d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
489edb35d95SEugene Zelenko 
490d3bd5b3dSLawrence D'Anna   PythonInteger() : TypedPythonObject() {} // MSVC requires this for some reason
491d3bd5b3dSLawrence D'Anna 
492d3bd5b3dSLawrence D'Anna   explicit PythonInteger(int64_t value);
4932c1f46dcSZachary Turner 
49422c8efcdSZachary Turner   static bool Check(PyObject *py_obj);
495d3bd5b3dSLawrence D'Anna   static void Convert(PyRefType &type, PyObject *&py_obj);
4962c1f46dcSZachary Turner 
497b9c1b51eSKate Stone   void SetInteger(int64_t value);
4982c1f46dcSZachary Turner 
4992c1f46dcSZachary Turner   StructuredData::IntegerSP CreateStructuredInteger() const;
5002c1f46dcSZachary Turner };
5012c1f46dcSZachary Turner 
502d3bd5b3dSLawrence D'Anna class PythonBoolean : public TypedPythonObject<PythonBoolean> {
503b81d715cSTatyana Krasnukha public:
504d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
505b81d715cSTatyana Krasnukha 
506d3bd5b3dSLawrence D'Anna   explicit PythonBoolean(bool value);
507b81d715cSTatyana Krasnukha 
508b81d715cSTatyana Krasnukha   static bool Check(PyObject *py_obj);
509b81d715cSTatyana Krasnukha 
510b81d715cSTatyana Krasnukha   bool GetValue() const;
511b81d715cSTatyana Krasnukha 
512b81d715cSTatyana Krasnukha   void SetValue(bool value);
513b81d715cSTatyana Krasnukha 
514b81d715cSTatyana Krasnukha   StructuredData::BooleanSP CreateStructuredBoolean() const;
515b81d715cSTatyana Krasnukha };
516b81d715cSTatyana Krasnukha 
517d3bd5b3dSLawrence D'Anna class PythonList : public TypedPythonObject<PythonList> {
5182c1f46dcSZachary Turner public:
519d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
520d3bd5b3dSLawrence D'Anna 
521d3bd5b3dSLawrence D'Anna   PythonList() : TypedPythonObject() {} // MSVC requires this for some reason
522d3bd5b3dSLawrence D'Anna 
52387f47729SZachary Turner   explicit PythonList(PyInitialValue value);
52487f47729SZachary Turner   explicit PythonList(int list_size);
5252c1f46dcSZachary Turner 
52622c8efcdSZachary Turner   static bool Check(PyObject *py_obj);
52722c8efcdSZachary Turner 
5282c1f46dcSZachary Turner   uint32_t GetSize() const;
5292c1f46dcSZachary Turner 
5302c1f46dcSZachary Turner   PythonObject GetItemAtIndex(uint32_t index) const;
5312c1f46dcSZachary Turner 
532f8b22f8fSZachary Turner   void SetItemAtIndex(uint32_t index, const PythonObject &object);
5332c1f46dcSZachary Turner 
534f8b22f8fSZachary Turner   void AppendItem(const PythonObject &object);
5352c1f46dcSZachary Turner 
5362c1f46dcSZachary Turner   StructuredData::ArraySP CreateStructuredArray() const;
5372c1f46dcSZachary Turner };
5382c1f46dcSZachary Turner 
539d3bd5b3dSLawrence D'Anna class PythonTuple : public TypedPythonObject<PythonTuple> {
540a1405147SZachary Turner public:
541d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
542d3bd5b3dSLawrence D'Anna 
543a1405147SZachary Turner   explicit PythonTuple(PyInitialValue value);
544a1405147SZachary Turner   explicit PythonTuple(int tuple_size);
545a1405147SZachary Turner   PythonTuple(std::initializer_list<PythonObject> objects);
546a1405147SZachary Turner   PythonTuple(std::initializer_list<PyObject *> objects);
547a1405147SZachary Turner 
548a1405147SZachary Turner   static bool Check(PyObject *py_obj);
549a1405147SZachary Turner 
550a1405147SZachary Turner   uint32_t GetSize() const;
551a1405147SZachary Turner 
552a1405147SZachary Turner   PythonObject GetItemAtIndex(uint32_t index) const;
553a1405147SZachary Turner 
554a1405147SZachary Turner   void SetItemAtIndex(uint32_t index, const PythonObject &object);
555a1405147SZachary Turner 
556a1405147SZachary Turner   StructuredData::ArraySP CreateStructuredArray() const;
557a1405147SZachary Turner };
558a1405147SZachary Turner 
559d3bd5b3dSLawrence D'Anna class PythonDictionary : public TypedPythonObject<PythonDictionary> {
5602c1f46dcSZachary Turner public:
561d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
562edb35d95SEugene Zelenko 
563d3bd5b3dSLawrence D'Anna   PythonDictionary() : TypedPythonObject() {} // MSVC requires this for some reason
564d3bd5b3dSLawrence D'Anna 
565d3bd5b3dSLawrence D'Anna   explicit PythonDictionary(PyInitialValue value);
5662c1f46dcSZachary Turner 
56722c8efcdSZachary Turner   static bool Check(PyObject *py_obj);
56822c8efcdSZachary Turner 
5692c1f46dcSZachary Turner   uint32_t GetSize() const;
5702c1f46dcSZachary Turner 
571f8b22f8fSZachary Turner   PythonList GetKeys() const;
5722c1f46dcSZachary Turner 
573c86a6acaSLawrence D'Anna   PythonObject GetItemForKey(const PythonObject &key) const; // DEPRECATED
574c86a6acaSLawrence D'Anna   void SetItemForKey(const PythonObject &key,
575c86a6acaSLawrence D'Anna                      const PythonObject &value); // DEPRECATED
576c86a6acaSLawrence D'Anna 
577c86a6acaSLawrence D'Anna   llvm::Expected<PythonObject> GetItem(const PythonObject &key) const;
578722b6189SLawrence D'Anna   llvm::Expected<PythonObject> GetItem(const llvm::Twine &key) const;
579c86a6acaSLawrence D'Anna   llvm::Error SetItem(const PythonObject &key, const PythonObject &value) const;
580722b6189SLawrence D'Anna   llvm::Error SetItem(const llvm::Twine &key, const PythonObject &value) const;
5812c1f46dcSZachary Turner 
5822c1f46dcSZachary Turner   StructuredData::DictionarySP CreateStructuredDictionary() const;
5832c1f46dcSZachary Turner };
58487f47729SZachary Turner 
585d3bd5b3dSLawrence D'Anna class PythonModule : public TypedPythonObject<PythonModule> {
5867841efbbSZachary Turner public:
587d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
5887841efbbSZachary Turner 
5897841efbbSZachary Turner   static bool Check(PyObject *py_obj);
5907841efbbSZachary Turner 
591b9c1b51eSKate Stone   static PythonModule BuiltinsModule();
592a1405147SZachary Turner 
593b9c1b51eSKate Stone   static PythonModule MainModule();
594a1405147SZachary Turner 
595b9c1b51eSKate Stone   static PythonModule AddModule(llvm::StringRef module);
5967841efbbSZachary Turner 
597085328eeSLawrence D'Anna   // safe, returns invalid on error;
598085328eeSLawrence D'Anna   static PythonModule ImportModule(llvm::StringRef name) {
599adcd0268SBenjamin Kramer     std::string s = std::string(name);
600085328eeSLawrence D'Anna     auto mod = Import(s.c_str());
601085328eeSLawrence D'Anna     if (!mod) {
602085328eeSLawrence D'Anna       llvm::consumeError(mod.takeError());
603085328eeSLawrence D'Anna       return PythonModule();
604085328eeSLawrence D'Anna     }
605085328eeSLawrence D'Anna     return std::move(mod.get());
606085328eeSLawrence D'Anna   }
607085328eeSLawrence D'Anna 
608722b6189SLawrence D'Anna   static llvm::Expected<PythonModule> Import(const llvm::Twine &name);
609085328eeSLawrence D'Anna 
610722b6189SLawrence D'Anna   llvm::Expected<PythonObject> Get(const llvm::Twine &name);
6112419f1d5SZachary Turner 
6127841efbbSZachary Turner   PythonDictionary GetDictionary() const;
6137841efbbSZachary Turner };
6147841efbbSZachary Turner 
615d3bd5b3dSLawrence D'Anna class PythonCallable : public TypedPythonObject<PythonCallable> {
616a1405147SZachary Turner public:
617d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
618d3bd5b3dSLawrence D'Anna 
619b58fb2f4SZachary Turner   struct ArgInfo {
6202386537cSLawrence D'Anna     /* the largest number of positional arguments this callable
6212386537cSLawrence D'Anna      * can accept, or UNBOUNDED, ie UINT_MAX if it's a varargs
6222386537cSLawrence D'Anna      * function and can accept an arbitrary number */
6232386537cSLawrence D'Anna     unsigned max_positional_args;
6242386537cSLawrence D'Anna     static constexpr unsigned UNBOUNDED = UINT_MAX; // FIXME c++17 inline
625b58fb2f4SZachary Turner   };
626b58fb2f4SZachary Turner 
627b9c1b51eSKate Stone   static bool Check(PyObject *py_obj);
628a1405147SZachary Turner 
629c86a6acaSLawrence D'Anna   llvm::Expected<ArgInfo> GetArgInfo() const;
630c86a6acaSLawrence D'Anna 
631b9c1b51eSKate Stone   PythonObject operator()();
632a1405147SZachary Turner 
633b9c1b51eSKate Stone   PythonObject operator()(std::initializer_list<PyObject *> args);
634a1405147SZachary Turner 
635b9c1b51eSKate Stone   PythonObject operator()(std::initializer_list<PythonObject> args);
636b58fb2f4SZachary Turner 
637b58fb2f4SZachary Turner   template <typename Arg, typename... Args>
638b9c1b51eSKate Stone   PythonObject operator()(const Arg &arg, Args... args) {
639b58fb2f4SZachary Turner     return operator()({arg, args...});
640b58fb2f4SZachary Turner   }
641a1405147SZachary Turner };
642a1405147SZachary Turner 
643d3bd5b3dSLawrence D'Anna class PythonFile : public TypedPythonObject<PythonFile> {
6449c40264fSZachary Turner public:
645d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
646edb35d95SEugene Zelenko 
647d3bd5b3dSLawrence D'Anna   PythonFile() : TypedPythonObject() {} // MSVC requires this for some reason
6489c40264fSZachary Turner 
6499c40264fSZachary Turner   static bool Check(PyObject *py_obj);
6509c40264fSZachary Turner 
651d9b553ecSLawrence D'Anna   static llvm::Expected<PythonFile> FromFile(File &file,
652d9b553ecSLawrence D'Anna                                              const char *mode = nullptr);
653d9b553ecSLawrence 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;
67204edd189SLawrence D'Anna   bool Matches(PyObject *exc) const;
67304edd189SLawrence D'Anna   std::string ReadBacktrace() const;
674085328eeSLawrence D'Anna };
675085328eeSLawrence D'Anna 
676085328eeSLawrence D'Anna // This extracts the underlying T out of an Expected<T> and returns it.
677085328eeSLawrence D'Anna // If the Expected is an Error instead of a T, that error will be converted
678085328eeSLawrence D'Anna // into a python exception, and this will return a default-constructed T.
679085328eeSLawrence D'Anna //
680085328eeSLawrence D'Anna // This is appropriate for use right at the boundary of python calling into
681085328eeSLawrence D'Anna // C++, such as in a SWIG typemap.   In such a context you should simply
682085328eeSLawrence D'Anna // check if the returned T is valid, and if it is, return a NULL back
683085328eeSLawrence D'Anna // to python.   This will result in the Error being raised as an exception
684085328eeSLawrence D'Anna // from python code's point of view.
685085328eeSLawrence D'Anna //
686085328eeSLawrence D'Anna // For example:
687085328eeSLawrence D'Anna // ```
688085328eeSLawrence D'Anna // Expected<Foo *> efoop = some_cpp_function();
689085328eeSLawrence D'Anna // Foo *foop = unwrapOrSetPythonException(efoop);
690085328eeSLawrence D'Anna // if (!foop)
691085328eeSLawrence D'Anna //    return NULL;
692085328eeSLawrence D'Anna // do_something(*foop);
693085328eeSLawrence D'Anna //
694085328eeSLawrence D'Anna // If the Error returned was itself created because a python exception was
695085328eeSLawrence D'Anna // raised when C++ code called into python, then the original exception
696085328eeSLawrence D'Anna // will be restored.   Otherwise a simple string exception will be raised.
697085328eeSLawrence D'Anna template <typename T> T unwrapOrSetPythonException(llvm::Expected<T> expected) {
698085328eeSLawrence D'Anna   if (expected)
699085328eeSLawrence D'Anna     return expected.get();
700085328eeSLawrence D'Anna   llvm::handleAllErrors(
701085328eeSLawrence D'Anna       expected.takeError(), [](PythonException &E) { E.Restore(); },
702085328eeSLawrence D'Anna       [](const llvm::ErrorInfoBase &E) {
703085328eeSLawrence D'Anna         PyErr_SetString(PyExc_Exception, E.message().c_str());
704085328eeSLawrence D'Anna       });
705085328eeSLawrence D'Anna   return T();
706085328eeSLawrence D'Anna }
707085328eeSLawrence D'Anna 
708722b6189SLawrence D'Anna // This is only here to help incrementally migrate old, exception-unsafe
709722b6189SLawrence D'Anna // code.
710722b6189SLawrence D'Anna template <typename T> T unwrapIgnoringErrors(llvm::Expected<T> expected) {
711722b6189SLawrence D'Anna   if (expected)
712722b6189SLawrence D'Anna     return std::move(expected.get());
713722b6189SLawrence D'Anna   llvm::consumeError(expected.takeError());
714722b6189SLawrence D'Anna   return T();
715722b6189SLawrence D'Anna }
716722b6189SLawrence D'Anna 
71704edd189SLawrence D'Anna llvm::Expected<PythonObject> runStringOneLine(const llvm::Twine &string,
71804edd189SLawrence D'Anna                                               const PythonDictionary &globals,
71904edd189SLawrence D'Anna                                               const PythonDictionary &locals);
72004edd189SLawrence D'Anna 
72104edd189SLawrence D'Anna llvm::Expected<PythonObject> runStringMultiLine(const llvm::Twine &string,
72204edd189SLawrence D'Anna                                                 const PythonDictionary &globals,
72304edd189SLawrence D'Anna                                                 const PythonDictionary &locals);
72404edd189SLawrence D'Anna 
72504edd189SLawrence D'Anna // Sometimes the best way to interact with a python interpreter is
72604edd189SLawrence D'Anna // to run some python code.   You construct a PythonScript with
72704edd189SLawrence D'Anna // script string.   The script assigns some function to `_function_`
72804edd189SLawrence D'Anna // and you get a C++ callable object that calls the python function.
72904edd189SLawrence D'Anna //
73004edd189SLawrence D'Anna // Example:
73104edd189SLawrence D'Anna //
73204edd189SLawrence D'Anna // const char script[] = R"(
73304edd189SLawrence D'Anna // def main(x, y):
73404edd189SLawrence D'Anna //    ....
73504edd189SLawrence D'Anna // )";
73604edd189SLawrence D'Anna //
73704edd189SLawrence D'Anna // Expected<PythonObject> cpp_foo_wrapper(PythonObject x, PythonObject y) {
73804edd189SLawrence D'Anna //   // no need to synchronize access to this global, we already have the GIL
73904edd189SLawrence D'Anna //   static PythonScript foo(script)
74004edd189SLawrence D'Anna //   return  foo(x, y);
74104edd189SLawrence D'Anna // }
74204edd189SLawrence D'Anna class PythonScript {
74304edd189SLawrence D'Anna   const char *script;
74404edd189SLawrence D'Anna   PythonCallable function;
74504edd189SLawrence D'Anna 
74604edd189SLawrence D'Anna   llvm::Error Init();
74704edd189SLawrence D'Anna 
74804edd189SLawrence D'Anna public:
74904edd189SLawrence D'Anna   PythonScript(const char *script) : script(script), function() {}
75004edd189SLawrence D'Anna 
75104edd189SLawrence D'Anna   template <typename... Args>
75204edd189SLawrence D'Anna   llvm::Expected<PythonObject> operator()(Args &&... args) {
75304edd189SLawrence D'Anna     if (llvm::Error error = Init())
75404edd189SLawrence D'Anna       return std::move(error);
75504edd189SLawrence D'Anna     return function.Call(std::forward<Args>(args)...);
75604edd189SLawrence D'Anna   }
75704edd189SLawrence D'Anna };
75804edd189SLawrence D'Anna 
75904edd189SLawrence D'Anna } // namespace python
7602c1f46dcSZachary Turner } // namespace lldb_private
7612c1f46dcSZachary Turner 
762a281b42bSZachary Turner #endif
763d68983e3SPavel Labath 
764d68983e3SPavel Labath #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
765