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 
74*bbef51ebSLawrence D'Anna class GIL {
75*bbef51ebSLawrence D'Anna public:
76*bbef51ebSLawrence D'Anna   GIL() {
77*bbef51ebSLawrence D'Anna     m_state = PyGILState_Ensure();
78*bbef51ebSLawrence D'Anna     assert(!PyErr_Occurred());
79*bbef51ebSLawrence D'Anna   }
80*bbef51ebSLawrence D'Anna   ~GIL() { PyGILState_Release(m_state); }
81*bbef51ebSLawrence D'Anna 
82*bbef51ebSLawrence D'Anna protected:
83*bbef51ebSLawrence D'Anna   PyGILState_STATE m_state;
84*bbef51ebSLawrence D'Anna };
85*bbef51ebSLawrence D'Anna 
86b9c1b51eSKate Stone class StructuredPythonObject : public StructuredData::Generic {
872c1f46dcSZachary Turner public:
88b9c1b51eSKate Stone   StructuredPythonObject() : StructuredData::Generic() {}
892c1f46dcSZachary Turner 
90b9c1b51eSKate Stone   StructuredPythonObject(void *obj) : StructuredData::Generic(obj) {
912c1f46dcSZachary Turner     Py_XINCREF(GetValue());
922c1f46dcSZachary Turner   }
932c1f46dcSZachary Turner 
94b9c1b51eSKate Stone   ~StructuredPythonObject() override {
952c1f46dcSZachary Turner     if (Py_IsInitialized())
962c1f46dcSZachary Turner       Py_XDECREF(GetValue());
972c1f46dcSZachary Turner     SetValue(nullptr);
982c1f46dcSZachary Turner   }
992c1f46dcSZachary Turner 
100b9c1b51eSKate Stone   bool IsValid() const override { return GetValue() && GetValue() != Py_None; }
1012c1f46dcSZachary Turner 
1022783d817SJonas Devlieghere   void Serialize(llvm::json::OStream &s) const override;
1032c1f46dcSZachary Turner 
1042c1f46dcSZachary Turner private:
105eaebcbc6SKonrad Kleine   StructuredPythonObject(const StructuredPythonObject &) = delete;
106eaebcbc6SKonrad Kleine   const StructuredPythonObject &
107eaebcbc6SKonrad Kleine   operator=(const StructuredPythonObject &) = delete;
1082c1f46dcSZachary Turner };
1092c1f46dcSZachary Turner 
110b9c1b51eSKate Stone enum class PyObjectType {
1112c1f46dcSZachary Turner   Unknown,
1122c1f46dcSZachary Turner   None,
113b81d715cSTatyana Krasnukha   Boolean,
1142c1f46dcSZachary Turner   Integer,
1152c1f46dcSZachary Turner   Dictionary,
1162c1f46dcSZachary Turner   List,
1179c40264fSZachary Turner   String,
1185a72c02bSZachary Turner   Bytes,
119f9d6d204SZachary Turner   ByteArray,
1207841efbbSZachary Turner   Module,
121a1405147SZachary Turner   Callable,
122a1405147SZachary Turner   Tuple,
1239c40264fSZachary Turner   File
1242c1f46dcSZachary Turner };
1252c1f46dcSZachary Turner 
126b9c1b51eSKate Stone enum class PyRefType {
127f8b22f8fSZachary Turner   Borrowed, // We are not given ownership of the incoming PyObject.
128f8b22f8fSZachary Turner             // We cannot safely hold it without calling Py_INCREF.
129f8b22f8fSZachary Turner   Owned     // We have ownership of the incoming PyObject.  We should
130f8b22f8fSZachary Turner             // not call Py_INCREF.
131f8b22f8fSZachary Turner };
132f8b22f8fSZachary Turner 
133085328eeSLawrence D'Anna 
134085328eeSLawrence D'Anna // Take a reference that you already own, and turn it into
135085328eeSLawrence D'Anna // a PythonObject.
136085328eeSLawrence D'Anna //
137085328eeSLawrence D'Anna // Most python API methods will return a +1 reference
138085328eeSLawrence D'Anna // if they succeed or NULL if and only if
139085328eeSLawrence D'Anna // they set an exception.   Use this to collect such return
140085328eeSLawrence D'Anna // values, after checking for NULL.
141085328eeSLawrence D'Anna //
142085328eeSLawrence D'Anna // If T is not just PythonObject, then obj must be already be
143085328eeSLawrence D'Anna // checked to be of the correct type.
144085328eeSLawrence D'Anna template <typename T> T Take(PyObject *obj) {
145085328eeSLawrence D'Anna   assert(obj);
146085328eeSLawrence D'Anna   assert(!PyErr_Occurred());
147085328eeSLawrence D'Anna   T thing(PyRefType::Owned, obj);
148085328eeSLawrence D'Anna   assert(thing.IsValid());
1491dfb1a85SPavel Labath   return thing;
150085328eeSLawrence D'Anna }
151085328eeSLawrence D'Anna 
152085328eeSLawrence D'Anna // Retain a reference you have borrowed, and turn it into
153085328eeSLawrence D'Anna // a PythonObject.
154085328eeSLawrence D'Anna //
155085328eeSLawrence D'Anna // A minority of python APIs return a borrowed reference
156085328eeSLawrence D'Anna // instead of a +1.   They will also return NULL if and only
157085328eeSLawrence D'Anna // if they set an exception.   Use this to collect such return
158085328eeSLawrence D'Anna // values, after checking for NULL.
159085328eeSLawrence D'Anna //
160085328eeSLawrence D'Anna // If T is not just PythonObject, then obj must be already be
161085328eeSLawrence D'Anna // checked to be of the correct type.
162085328eeSLawrence D'Anna template <typename T> T Retain(PyObject *obj) {
163085328eeSLawrence D'Anna   assert(obj);
164085328eeSLawrence D'Anna   assert(!PyErr_Occurred());
165085328eeSLawrence D'Anna   T thing(PyRefType::Borrowed, obj);
166085328eeSLawrence D'Anna   assert(thing.IsValid());
1671dfb1a85SPavel Labath   return thing;
168085328eeSLawrence D'Anna }
169085328eeSLawrence D'Anna 
170722b6189SLawrence D'Anna // This class can be used like a utility function to convert from
171722b6189SLawrence D'Anna // a llvm-friendly Twine into a null-terminated const char *,
172722b6189SLawrence D'Anna // which is the form python C APIs want their strings in.
173722b6189SLawrence D'Anna //
174722b6189SLawrence D'Anna // Example:
175722b6189SLawrence D'Anna // const llvm::Twine &some_twine;
176722b6189SLawrence D'Anna // PyFoo_Bar(x, y, z, NullTerminated(some_twine));
177722b6189SLawrence D'Anna //
178722b6189SLawrence D'Anna // Why a class instead of a function?  If the twine isn't already null
179722b6189SLawrence D'Anna // terminated, it will need a temporary buffer to copy the string
180722b6189SLawrence D'Anna // into.   We need that buffer to stick around for the lifetime of the
181722b6189SLawrence D'Anna // statement.
182722b6189SLawrence D'Anna class NullTerminated {
183722b6189SLawrence D'Anna   const char *str;
184722b6189SLawrence D'Anna   llvm::SmallString<32> storage;
185722b6189SLawrence D'Anna 
186722b6189SLawrence D'Anna public:
187722b6189SLawrence D'Anna   NullTerminated(const llvm::Twine &twine) {
188722b6189SLawrence D'Anna     llvm::StringRef ref = twine.toNullTerminatedStringRef(storage);
189722b6189SLawrence D'Anna     str = ref.begin();
190722b6189SLawrence D'Anna   }
191722b6189SLawrence D'Anna   operator const char *() { return str; }
192722b6189SLawrence D'Anna };
193722b6189SLawrence D'Anna 
19404edd189SLawrence D'Anna inline llvm::Error nullDeref() {
19504edd189SLawrence D'Anna   return llvm::createStringError(llvm::inconvertibleErrorCode(),
19604edd189SLawrence D'Anna                                  "A NULL PyObject* was dereferenced");
19704edd189SLawrence D'Anna }
19804edd189SLawrence D'Anna 
19904edd189SLawrence D'Anna inline llvm::Error exception(const char *s = nullptr) {
20004edd189SLawrence D'Anna   return llvm::make_error<PythonException>(s);
20104edd189SLawrence D'Anna }
20204edd189SLawrence D'Anna 
20304edd189SLawrence D'Anna inline llvm::Error keyError() {
20404edd189SLawrence D'Anna   return llvm::createStringError(llvm::inconvertibleErrorCode(),
20504edd189SLawrence D'Anna                                  "key not in dict");
20604edd189SLawrence D'Anna }
207085328eeSLawrence D'Anna 
2086a93a12aSLawrence D'Anna #if PY_MAJOR_VERSION < 3
2096a93a12aSLawrence D'Anna // The python 2 API declares some arguments as char* that should
2106a93a12aSLawrence D'Anna // be const char *, but it doesn't actually modify them.
2116a93a12aSLawrence D'Anna inline char *py2_const_cast(const char *s) { return const_cast<char *>(s); }
2126a93a12aSLawrence D'Anna #else
2136a93a12aSLawrence D'Anna inline const char *py2_const_cast(const char *s) { return s; }
2146a93a12aSLawrence D'Anna #endif
2156a93a12aSLawrence D'Anna 
216b9c1b51eSKate Stone enum class PyInitialValue { Invalid, Empty };
217f8b22f8fSZachary Turner 
218085328eeSLawrence D'Anna template <typename T, typename Enable = void> struct PythonFormat;
219085328eeSLawrence D'Anna 
220085328eeSLawrence D'Anna template <> struct PythonFormat<unsigned long long> {
221085328eeSLawrence D'Anna   static constexpr char format = 'K';
222085328eeSLawrence D'Anna   static auto get(unsigned long long value) { return value; }
223085328eeSLawrence D'Anna };
224085328eeSLawrence D'Anna 
225085328eeSLawrence D'Anna template <> struct PythonFormat<long long> {
226085328eeSLawrence D'Anna   static constexpr char format = 'L';
227085328eeSLawrence D'Anna   static auto get(long long value) { return value; }
228085328eeSLawrence D'Anna };
229085328eeSLawrence D'Anna 
23004edd189SLawrence D'Anna template <> struct PythonFormat<PyObject *> {
23104edd189SLawrence D'Anna   static constexpr char format = 'O';
23204edd189SLawrence D'Anna   static auto get(PyObject *value) { return value; }
23304edd189SLawrence D'Anna };
23404edd189SLawrence D'Anna 
235085328eeSLawrence D'Anna template <typename T>
236085328eeSLawrence D'Anna struct PythonFormat<
237085328eeSLawrence D'Anna     T, typename std::enable_if<std::is_base_of<PythonObject, T>::value>::type> {
238085328eeSLawrence D'Anna   static constexpr char format = 'O';
239085328eeSLawrence D'Anna   static auto get(const T &value) { return value.get(); }
240085328eeSLawrence D'Anna };
241085328eeSLawrence D'Anna 
242b9c1b51eSKate Stone class PythonObject {
2432c1f46dcSZachary Turner public:
244fd2433e1SJonas Devlieghere   PythonObject() = default;
2452c1f46dcSZachary Turner 
24604edd189SLawrence D'Anna   PythonObject(PyRefType type, PyObject *py_obj) {
24704edd189SLawrence D'Anna     m_py_obj = py_obj;
24804edd189SLawrence D'Anna     // If this is a borrowed reference, we need to convert it to
24904edd189SLawrence D'Anna     // an owned reference by incrementing it.  If it is an owned
25004edd189SLawrence D'Anna     // reference (for example the caller allocated it with PyDict_New()
25104edd189SLawrence D'Anna     // then we must *not* increment it.
25204edd189SLawrence D'Anna     if (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed)
25304edd189SLawrence D'Anna       Py_XINCREF(m_py_obj);
2542c1f46dcSZachary Turner   }
2552c1f46dcSZachary Turner 
25603819d1cSLawrence D'Anna   PythonObject(const PythonObject &rhs)
25703819d1cSLawrence D'Anna       : PythonObject(PyRefType::Borrowed, rhs.m_py_obj) {}
2582c1f46dcSZachary Turner 
259085328eeSLawrence D'Anna   PythonObject(PythonObject &&rhs) {
260085328eeSLawrence D'Anna     m_py_obj = rhs.m_py_obj;
261085328eeSLawrence D'Anna     rhs.m_py_obj = nullptr;
262085328eeSLawrence D'Anna   }
263085328eeSLawrence D'Anna 
264d3bd5b3dSLawrence D'Anna   ~PythonObject() { Reset(); }
2652c1f46dcSZachary Turner 
266b9c1b51eSKate Stone   void Reset() {
267085328eeSLawrence D'Anna     if (m_py_obj && Py_IsInitialized())
268085328eeSLawrence D'Anna       Py_DECREF(m_py_obj);
269f8b22f8fSZachary Turner     m_py_obj = nullptr;
2702c1f46dcSZachary Turner   }
271f8b22f8fSZachary Turner 
272b9c1b51eSKate Stone   void Dump() const {
2732c1f46dcSZachary Turner     if (m_py_obj)
2742c1f46dcSZachary Turner       _PyObject_Dump(m_py_obj);
2752c1f46dcSZachary Turner     else
2762c1f46dcSZachary Turner       puts("NULL");
2772c1f46dcSZachary Turner   }
2782c1f46dcSZachary Turner 
279b9c1b51eSKate Stone   void Dump(Stream &strm) const;
2802c1f46dcSZachary Turner 
281b9c1b51eSKate Stone   PyObject *get() const { return m_py_obj; }
2822c1f46dcSZachary Turner 
283b9c1b51eSKate Stone   PyObject *release() {
28460c24f70SZachary Turner     PyObject *result = m_py_obj;
28560c24f70SZachary Turner     m_py_obj = nullptr;
28660c24f70SZachary Turner     return result;
28760c24f70SZachary Turner   }
28860c24f70SZachary Turner 
28903819d1cSLawrence D'Anna   PythonObject &operator=(PythonObject other) {
290085328eeSLawrence D'Anna     Reset();
29103819d1cSLawrence D'Anna     m_py_obj = std::exchange(other.m_py_obj, nullptr);
292085328eeSLawrence D'Anna     return *this;
293085328eeSLawrence D'Anna   }
294085328eeSLawrence D'Anna 
295b9c1b51eSKate Stone   PyObjectType GetObjectType() const;
2967841efbbSZachary Turner 
297b9c1b51eSKate Stone   PythonString Repr() const;
2987841efbbSZachary Turner 
299b9c1b51eSKate Stone   PythonString Str() const;
3007841efbbSZachary Turner 
301b9c1b51eSKate Stone   static PythonObject ResolveNameWithDictionary(llvm::StringRef name,
302b9c1b51eSKate Stone                                                 const PythonDictionary &dict);
3037841efbbSZachary Turner 
304b58fb2f4SZachary Turner   template <typename T>
305b9c1b51eSKate Stone   static T ResolveNameWithDictionary(llvm::StringRef name,
306b9c1b51eSKate Stone                                      const PythonDictionary &dict) {
307b58fb2f4SZachary Turner     return ResolveNameWithDictionary(name, dict).AsType<T>();
308b58fb2f4SZachary Turner   }
309b58fb2f4SZachary Turner 
310b9c1b51eSKate Stone   PythonObject ResolveName(llvm::StringRef name) const;
3117841efbbSZachary Turner 
312b9c1b51eSKate Stone   template <typename T> T ResolveName(llvm::StringRef name) const {
313b58fb2f4SZachary Turner     return ResolveName(name).AsType<T>();
314b58fb2f4SZachary Turner   }
315b58fb2f4SZachary Turner 
316b9c1b51eSKate Stone   bool HasAttribute(llvm::StringRef attribute) const;
3179c40264fSZachary Turner 
318b9c1b51eSKate Stone   PythonObject GetAttributeValue(llvm::StringRef attribute) const;
3197d6d218eSZachary Turner 
320085328eeSLawrence D'Anna   bool IsNone() const { return m_py_obj == Py_None; }
321f8b22f8fSZachary Turner 
322085328eeSLawrence D'Anna   bool IsValid() const { return m_py_obj != nullptr; }
323f8b22f8fSZachary Turner 
324085328eeSLawrence D'Anna   bool IsAllocated() const { return IsValid() && !IsNone(); }
325085328eeSLawrence D'Anna 
326085328eeSLawrence D'Anna   explicit operator bool() const { return IsValid() && !IsNone(); }
3272c1f46dcSZachary Turner 
328b9c1b51eSKate Stone   template <typename T> T AsType() const {
3297d6d218eSZachary Turner     if (!T::Check(m_py_obj))
3307d6d218eSZachary Turner       return T();
3317d6d218eSZachary Turner     return T(PyRefType::Borrowed, m_py_obj);
3327d6d218eSZachary Turner   }
3337d6d218eSZachary Turner 
334b9c1b51eSKate Stone   StructuredData::ObjectSP CreateStructuredObject() const;
3352c1f46dcSZachary Turner 
336085328eeSLawrence D'Anna   template <typename... T>
337085328eeSLawrence D'Anna   llvm::Expected<PythonObject> CallMethod(const char *name,
338085328eeSLawrence D'Anna                                           const T &... t) const {
339085328eeSLawrence D'Anna     const char format[] = {'(', PythonFormat<T>::format..., ')', 0};
340085328eeSLawrence D'Anna     PyObject *obj =
341c86a6acaSLawrence D'Anna         PyObject_CallMethod(m_py_obj, py2_const_cast(name),
342c86a6acaSLawrence D'Anna                             py2_const_cast(format), PythonFormat<T>::get(t)...);
343c86a6acaSLawrence D'Anna     if (!obj)
344c86a6acaSLawrence D'Anna       return exception();
345c86a6acaSLawrence D'Anna     return python::Take<PythonObject>(obj);
346c86a6acaSLawrence D'Anna   }
347c86a6acaSLawrence D'Anna 
348c86a6acaSLawrence D'Anna   template <typename... T>
349c86a6acaSLawrence D'Anna   llvm::Expected<PythonObject> Call(const T &... t) const {
350c86a6acaSLawrence D'Anna     const char format[] = {'(', PythonFormat<T>::format..., ')', 0};
351c86a6acaSLawrence D'Anna     PyObject *obj = PyObject_CallFunction(m_py_obj, py2_const_cast(format),
352c86a6acaSLawrence D'Anna                                           PythonFormat<T>::get(t)...);
353085328eeSLawrence D'Anna     if (!obj)
354085328eeSLawrence D'Anna       return exception();
355085328eeSLawrence D'Anna     return python::Take<PythonObject>(obj);
356085328eeSLawrence D'Anna   }
357085328eeSLawrence D'Anna 
358722b6189SLawrence D'Anna   llvm::Expected<PythonObject> GetAttribute(const llvm::Twine &name) const {
359085328eeSLawrence D'Anna     if (!m_py_obj)
360085328eeSLawrence D'Anna       return nullDeref();
361722b6189SLawrence D'Anna     PyObject *obj = PyObject_GetAttrString(m_py_obj, NullTerminated(name));
362085328eeSLawrence D'Anna     if (!obj)
363085328eeSLawrence D'Anna       return exception();
364085328eeSLawrence D'Anna     return python::Take<PythonObject>(obj);
365085328eeSLawrence D'Anna   }
366085328eeSLawrence D'Anna 
367085328eeSLawrence D'Anna   llvm::Expected<bool> IsTrue() {
368085328eeSLawrence D'Anna     if (!m_py_obj)
369085328eeSLawrence D'Anna       return nullDeref();
370085328eeSLawrence D'Anna     int r = PyObject_IsTrue(m_py_obj);
371085328eeSLawrence D'Anna     if (r < 0)
372085328eeSLawrence D'Anna       return exception();
373085328eeSLawrence D'Anna     return !!r;
374085328eeSLawrence D'Anna   }
375085328eeSLawrence D'Anna 
37652712d3fSLawrence D'Anna   llvm::Expected<long long> AsLongLong() const;
37752712d3fSLawrence D'Anna 
37852712d3fSLawrence D'Anna   llvm::Expected<long long> AsUnsignedLongLong() const;
37952712d3fSLawrence D'Anna 
38052712d3fSLawrence D'Anna   // wraps on overflow, instead of raising an error.
38152712d3fSLawrence D'Anna   llvm::Expected<unsigned long long> AsModuloUnsignedLongLong() const;
382085328eeSLawrence D'Anna 
383085328eeSLawrence D'Anna   llvm::Expected<bool> IsInstance(const PythonObject &cls) {
384085328eeSLawrence D'Anna     if (!m_py_obj || !cls.IsValid())
385085328eeSLawrence D'Anna       return nullDeref();
386085328eeSLawrence D'Anna     int r = PyObject_IsInstance(m_py_obj, cls.get());
387085328eeSLawrence D'Anna     if (r < 0)
388085328eeSLawrence D'Anna       return exception();
389085328eeSLawrence D'Anna     return !!r;
390085328eeSLawrence D'Anna   }
391085328eeSLawrence D'Anna 
392085328eeSLawrence D'Anna protected:
3939494c510SJonas Devlieghere   PyObject *m_py_obj = nullptr;
3942c1f46dcSZachary Turner };
3952c1f46dcSZachary Turner 
396085328eeSLawrence D'Anna 
397085328eeSLawrence D'Anna // This is why C++ needs monads.
398085328eeSLawrence D'Anna template <typename T> llvm::Expected<T> As(llvm::Expected<PythonObject> &&obj) {
399085328eeSLawrence D'Anna   if (!obj)
400085328eeSLawrence D'Anna     return obj.takeError();
401085328eeSLawrence D'Anna   if (!T::Check(obj.get().get()))
402085328eeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
403085328eeSLawrence D'Anna                                    "type error");
404085328eeSLawrence D'Anna   return T(PyRefType::Borrowed, std::move(obj.get().get()));
405085328eeSLawrence D'Anna }
406085328eeSLawrence D'Anna 
407085328eeSLawrence D'Anna template <> llvm::Expected<bool> As<bool>(llvm::Expected<PythonObject> &&obj);
408085328eeSLawrence D'Anna 
409085328eeSLawrence D'Anna template <>
410085328eeSLawrence D'Anna llvm::Expected<long long> As<long long>(llvm::Expected<PythonObject> &&obj);
411085328eeSLawrence D'Anna 
412c86a6acaSLawrence D'Anna template <>
41352712d3fSLawrence D'Anna llvm::Expected<unsigned long long>
41452712d3fSLawrence D'Anna As<unsigned long long>(llvm::Expected<PythonObject> &&obj);
41552712d3fSLawrence D'Anna 
41652712d3fSLawrence D'Anna template <>
417c86a6acaSLawrence D'Anna llvm::Expected<std::string> As<std::string>(llvm::Expected<PythonObject> &&obj);
418c86a6acaSLawrence D'Anna 
419085328eeSLawrence D'Anna 
420d3bd5b3dSLawrence D'Anna template <class T> class TypedPythonObject : public PythonObject {
4215a72c02bSZachary Turner public:
422d3bd5b3dSLawrence D'Anna   // override to perform implicit type conversions on Reset
423d3bd5b3dSLawrence D'Anna   // This can be eliminated once we drop python 2 support.
424d3bd5b3dSLawrence D'Anna   static void Convert(PyRefType &type, PyObject *&py_obj) {}
425d3bd5b3dSLawrence D'Anna 
426722b6189SLawrence D'Anna   TypedPythonObject(PyRefType type, PyObject *py_obj) {
427d3bd5b3dSLawrence D'Anna     if (!py_obj)
428d3bd5b3dSLawrence D'Anna       return;
429d3bd5b3dSLawrence D'Anna     T::Convert(type, py_obj);
430d3bd5b3dSLawrence D'Anna     if (T::Check(py_obj))
43104edd189SLawrence D'Anna       PythonObject::operator=(PythonObject(type, py_obj));
432d3bd5b3dSLawrence D'Anna     else if (type == PyRefType::Owned)
433d3bd5b3dSLawrence D'Anna       Py_DECREF(py_obj);
434d3bd5b3dSLawrence D'Anna   }
435d3bd5b3dSLawrence D'Anna 
436fd2433e1SJonas Devlieghere   TypedPythonObject() = default;
437d3bd5b3dSLawrence D'Anna };
438d3bd5b3dSLawrence D'Anna 
439d3bd5b3dSLawrence D'Anna class PythonBytes : public TypedPythonObject<PythonBytes> {
440d3bd5b3dSLawrence D'Anna public:
441d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
4425a72c02bSZachary Turner   explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes);
4435a72c02bSZachary Turner   PythonBytes(const uint8_t *bytes, size_t length);
4445a72c02bSZachary Turner 
445b9c1b51eSKate Stone   static bool Check(PyObject *py_obj);
4465a72c02bSZachary Turner 
447b9c1b51eSKate Stone   llvm::ArrayRef<uint8_t> GetBytes() const;
4485a72c02bSZachary Turner 
449b9c1b51eSKate Stone   size_t GetSize() const;
4505a72c02bSZachary Turner 
451b9c1b51eSKate Stone   void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
4525a72c02bSZachary Turner 
453b9c1b51eSKate Stone   StructuredData::StringSP CreateStructuredString() const;
4545a72c02bSZachary Turner };
4555a72c02bSZachary Turner 
456d3bd5b3dSLawrence D'Anna class PythonByteArray : public TypedPythonObject<PythonByteArray> {
457f9d6d204SZachary Turner public:
458d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
459f9d6d204SZachary Turner   explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes);
460f9d6d204SZachary Turner   PythonByteArray(const uint8_t *bytes, size_t length);
461f9d6d204SZachary Turner   PythonByteArray(const PythonBytes &object);
462f9d6d204SZachary Turner 
463b9c1b51eSKate Stone   static bool Check(PyObject *py_obj);
464f9d6d204SZachary Turner 
465b9c1b51eSKate Stone   llvm::ArrayRef<uint8_t> GetBytes() const;
466f9d6d204SZachary Turner 
467b9c1b51eSKate Stone   size_t GetSize() const;
468f9d6d204SZachary Turner 
469b9c1b51eSKate Stone   void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
470f9d6d204SZachary Turner 
471b9c1b51eSKate Stone   StructuredData::StringSP CreateStructuredString() const;
472f9d6d204SZachary Turner };
473f9d6d204SZachary Turner 
474d3bd5b3dSLawrence D'Anna class PythonString : public TypedPythonObject<PythonString> {
4752c1f46dcSZachary Turner public:
476d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
477085328eeSLawrence D'Anna   static llvm::Expected<PythonString> FromUTF8(llvm::StringRef string);
478085328eeSLawrence D'Anna 
479d3bd5b3dSLawrence D'Anna   PythonString() : TypedPythonObject() {} // MSVC requires this for some reason
480edb35d95SEugene Zelenko 
481d3bd5b3dSLawrence D'Anna   explicit PythonString(llvm::StringRef string); // safe, null on error
4822c1f46dcSZachary Turner 
48322c8efcdSZachary Turner   static bool Check(PyObject *py_obj);
484d3bd5b3dSLawrence D'Anna   static void Convert(PyRefType &type, PyObject *&py_obj);
4852c1f46dcSZachary Turner 
486085328eeSLawrence D'Anna   llvm::StringRef GetString() const; // safe, empty string on error
487085328eeSLawrence D'Anna 
488085328eeSLawrence D'Anna   llvm::Expected<llvm::StringRef> AsUTF8() const;
4892c1f46dcSZachary Turner 
490b9c1b51eSKate Stone   size_t GetSize() const;
4912c1f46dcSZachary Turner 
492085328eeSLawrence D'Anna   void SetString(llvm::StringRef string); // safe, null on error
4932c1f46dcSZachary Turner 
4942c1f46dcSZachary Turner   StructuredData::StringSP CreateStructuredString() const;
4952c1f46dcSZachary Turner };
4962c1f46dcSZachary Turner 
497d3bd5b3dSLawrence D'Anna class PythonInteger : public TypedPythonObject<PythonInteger> {
4982c1f46dcSZachary Turner public:
499d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
500edb35d95SEugene Zelenko 
501d3bd5b3dSLawrence D'Anna   PythonInteger() : TypedPythonObject() {} // MSVC requires this for some reason
502d3bd5b3dSLawrence D'Anna 
503d3bd5b3dSLawrence D'Anna   explicit PythonInteger(int64_t value);
5042c1f46dcSZachary Turner 
50522c8efcdSZachary Turner   static bool Check(PyObject *py_obj);
506d3bd5b3dSLawrence D'Anna   static void Convert(PyRefType &type, PyObject *&py_obj);
5072c1f46dcSZachary Turner 
508b9c1b51eSKate Stone   void SetInteger(int64_t value);
5092c1f46dcSZachary Turner 
5102c1f46dcSZachary Turner   StructuredData::IntegerSP CreateStructuredInteger() const;
5112c1f46dcSZachary Turner };
5122c1f46dcSZachary Turner 
513d3bd5b3dSLawrence D'Anna class PythonBoolean : public TypedPythonObject<PythonBoolean> {
514b81d715cSTatyana Krasnukha public:
515d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
516b81d715cSTatyana Krasnukha 
517d3bd5b3dSLawrence D'Anna   explicit PythonBoolean(bool value);
518b81d715cSTatyana Krasnukha 
519b81d715cSTatyana Krasnukha   static bool Check(PyObject *py_obj);
520b81d715cSTatyana Krasnukha 
521b81d715cSTatyana Krasnukha   bool GetValue() const;
522b81d715cSTatyana Krasnukha 
523b81d715cSTatyana Krasnukha   void SetValue(bool value);
524b81d715cSTatyana Krasnukha 
525b81d715cSTatyana Krasnukha   StructuredData::BooleanSP CreateStructuredBoolean() const;
526b81d715cSTatyana Krasnukha };
527b81d715cSTatyana Krasnukha 
528d3bd5b3dSLawrence D'Anna class PythonList : public TypedPythonObject<PythonList> {
5292c1f46dcSZachary Turner public:
530d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
531d3bd5b3dSLawrence D'Anna 
532d3bd5b3dSLawrence D'Anna   PythonList() : TypedPythonObject() {} // MSVC requires this for some reason
533d3bd5b3dSLawrence D'Anna 
53487f47729SZachary Turner   explicit PythonList(PyInitialValue value);
53587f47729SZachary Turner   explicit PythonList(int list_size);
5362c1f46dcSZachary Turner 
53722c8efcdSZachary Turner   static bool Check(PyObject *py_obj);
53822c8efcdSZachary Turner 
5392c1f46dcSZachary Turner   uint32_t GetSize() const;
5402c1f46dcSZachary Turner 
5412c1f46dcSZachary Turner   PythonObject GetItemAtIndex(uint32_t index) const;
5422c1f46dcSZachary Turner 
543f8b22f8fSZachary Turner   void SetItemAtIndex(uint32_t index, const PythonObject &object);
5442c1f46dcSZachary Turner 
545f8b22f8fSZachary Turner   void AppendItem(const PythonObject &object);
5462c1f46dcSZachary Turner 
5472c1f46dcSZachary Turner   StructuredData::ArraySP CreateStructuredArray() const;
5482c1f46dcSZachary Turner };
5492c1f46dcSZachary Turner 
550d3bd5b3dSLawrence D'Anna class PythonTuple : public TypedPythonObject<PythonTuple> {
551a1405147SZachary Turner public:
552d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
553d3bd5b3dSLawrence D'Anna 
554a1405147SZachary Turner   explicit PythonTuple(PyInitialValue value);
555a1405147SZachary Turner   explicit PythonTuple(int tuple_size);
556a1405147SZachary Turner   PythonTuple(std::initializer_list<PythonObject> objects);
557a1405147SZachary Turner   PythonTuple(std::initializer_list<PyObject *> objects);
558a1405147SZachary Turner 
559a1405147SZachary Turner   static bool Check(PyObject *py_obj);
560a1405147SZachary Turner 
561a1405147SZachary Turner   uint32_t GetSize() const;
562a1405147SZachary Turner 
563a1405147SZachary Turner   PythonObject GetItemAtIndex(uint32_t index) const;
564a1405147SZachary Turner 
565a1405147SZachary Turner   void SetItemAtIndex(uint32_t index, const PythonObject &object);
566a1405147SZachary Turner 
567a1405147SZachary Turner   StructuredData::ArraySP CreateStructuredArray() const;
568a1405147SZachary Turner };
569a1405147SZachary Turner 
570d3bd5b3dSLawrence D'Anna class PythonDictionary : public TypedPythonObject<PythonDictionary> {
5712c1f46dcSZachary Turner public:
572d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
573edb35d95SEugene Zelenko 
574d3bd5b3dSLawrence D'Anna   PythonDictionary() : TypedPythonObject() {} // MSVC requires this for some reason
575d3bd5b3dSLawrence D'Anna 
576d3bd5b3dSLawrence D'Anna   explicit PythonDictionary(PyInitialValue value);
5772c1f46dcSZachary Turner 
57822c8efcdSZachary Turner   static bool Check(PyObject *py_obj);
57922c8efcdSZachary Turner 
5802c1f46dcSZachary Turner   uint32_t GetSize() const;
5812c1f46dcSZachary Turner 
582f8b22f8fSZachary Turner   PythonList GetKeys() const;
5832c1f46dcSZachary Turner 
584c86a6acaSLawrence D'Anna   PythonObject GetItemForKey(const PythonObject &key) const; // DEPRECATED
585c86a6acaSLawrence D'Anna   void SetItemForKey(const PythonObject &key,
586c86a6acaSLawrence D'Anna                      const PythonObject &value); // DEPRECATED
587c86a6acaSLawrence D'Anna 
588c86a6acaSLawrence D'Anna   llvm::Expected<PythonObject> GetItem(const PythonObject &key) const;
589722b6189SLawrence D'Anna   llvm::Expected<PythonObject> GetItem(const llvm::Twine &key) const;
590c86a6acaSLawrence D'Anna   llvm::Error SetItem(const PythonObject &key, const PythonObject &value) const;
591722b6189SLawrence D'Anna   llvm::Error SetItem(const llvm::Twine &key, const PythonObject &value) const;
5922c1f46dcSZachary Turner 
5932c1f46dcSZachary Turner   StructuredData::DictionarySP CreateStructuredDictionary() const;
5942c1f46dcSZachary Turner };
59587f47729SZachary Turner 
596d3bd5b3dSLawrence D'Anna class PythonModule : public TypedPythonObject<PythonModule> {
5977841efbbSZachary Turner public:
598d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
5997841efbbSZachary Turner 
6007841efbbSZachary Turner   static bool Check(PyObject *py_obj);
6017841efbbSZachary Turner 
602b9c1b51eSKate Stone   static PythonModule BuiltinsModule();
603a1405147SZachary Turner 
604b9c1b51eSKate Stone   static PythonModule MainModule();
605a1405147SZachary Turner 
606b9c1b51eSKate Stone   static PythonModule AddModule(llvm::StringRef module);
6077841efbbSZachary Turner 
608085328eeSLawrence D'Anna   // safe, returns invalid on error;
609085328eeSLawrence D'Anna   static PythonModule ImportModule(llvm::StringRef name) {
610adcd0268SBenjamin Kramer     std::string s = std::string(name);
611085328eeSLawrence D'Anna     auto mod = Import(s.c_str());
612085328eeSLawrence D'Anna     if (!mod) {
613085328eeSLawrence D'Anna       llvm::consumeError(mod.takeError());
614085328eeSLawrence D'Anna       return PythonModule();
615085328eeSLawrence D'Anna     }
616085328eeSLawrence D'Anna     return std::move(mod.get());
617085328eeSLawrence D'Anna   }
618085328eeSLawrence D'Anna 
619722b6189SLawrence D'Anna   static llvm::Expected<PythonModule> Import(const llvm::Twine &name);
620085328eeSLawrence D'Anna 
621722b6189SLawrence D'Anna   llvm::Expected<PythonObject> Get(const llvm::Twine &name);
6222419f1d5SZachary Turner 
6237841efbbSZachary Turner   PythonDictionary GetDictionary() const;
6247841efbbSZachary Turner };
6257841efbbSZachary Turner 
626d3bd5b3dSLawrence D'Anna class PythonCallable : public TypedPythonObject<PythonCallable> {
627a1405147SZachary Turner public:
628d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
629d3bd5b3dSLawrence D'Anna 
630b58fb2f4SZachary Turner   struct ArgInfo {
6312386537cSLawrence D'Anna     /* the largest number of positional arguments this callable
6322386537cSLawrence D'Anna      * can accept, or UNBOUNDED, ie UINT_MAX if it's a varargs
6332386537cSLawrence D'Anna      * function and can accept an arbitrary number */
6342386537cSLawrence D'Anna     unsigned max_positional_args;
6352386537cSLawrence D'Anna     static constexpr unsigned UNBOUNDED = UINT_MAX; // FIXME c++17 inline
636b58fb2f4SZachary Turner   };
637b58fb2f4SZachary Turner 
638b9c1b51eSKate Stone   static bool Check(PyObject *py_obj);
639a1405147SZachary Turner 
640c86a6acaSLawrence D'Anna   llvm::Expected<ArgInfo> GetArgInfo() const;
641c86a6acaSLawrence D'Anna 
642b9c1b51eSKate Stone   PythonObject operator()();
643a1405147SZachary Turner 
644b9c1b51eSKate Stone   PythonObject operator()(std::initializer_list<PyObject *> args);
645a1405147SZachary Turner 
646b9c1b51eSKate Stone   PythonObject operator()(std::initializer_list<PythonObject> args);
647b58fb2f4SZachary Turner 
648b58fb2f4SZachary Turner   template <typename Arg, typename... Args>
649b9c1b51eSKate Stone   PythonObject operator()(const Arg &arg, Args... args) {
650b58fb2f4SZachary Turner     return operator()({arg, args...});
651b58fb2f4SZachary Turner   }
652a1405147SZachary Turner };
653a1405147SZachary Turner 
654d3bd5b3dSLawrence D'Anna class PythonFile : public TypedPythonObject<PythonFile> {
6559c40264fSZachary Turner public:
656d3bd5b3dSLawrence D'Anna   using TypedPythonObject::TypedPythonObject;
657edb35d95SEugene Zelenko 
658d3bd5b3dSLawrence D'Anna   PythonFile() : TypedPythonObject() {} // MSVC requires this for some reason
6599c40264fSZachary Turner 
6609c40264fSZachary Turner   static bool Check(PyObject *py_obj);
6619c40264fSZachary Turner 
662d9b553ecSLawrence D'Anna   static llvm::Expected<PythonFile> FromFile(File &file,
663d9b553ecSLawrence D'Anna                                              const char *mode = nullptr);
664d9b553ecSLawrence D'Anna 
665085328eeSLawrence D'Anna   llvm::Expected<lldb::FileSP> ConvertToFile(bool borrowed = false);
666085328eeSLawrence D'Anna   llvm::Expected<lldb::FileSP>
667085328eeSLawrence D'Anna   ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed = false);
6689c40264fSZachary Turner };
6699c40264fSZachary Turner 
670085328eeSLawrence D'Anna class PythonException : public llvm::ErrorInfo<PythonException> {
671085328eeSLawrence D'Anna private:
672085328eeSLawrence D'Anna   PyObject *m_exception_type, *m_exception, *m_traceback;
673085328eeSLawrence D'Anna   PyObject *m_repr_bytes;
674085328eeSLawrence D'Anna 
675085328eeSLawrence D'Anna public:
676085328eeSLawrence D'Anna   static char ID;
677085328eeSLawrence D'Anna   const char *toCString() const;
678085328eeSLawrence D'Anna   PythonException(const char *caller = nullptr);
679085328eeSLawrence D'Anna   void Restore();
680085328eeSLawrence D'Anna   ~PythonException();
681085328eeSLawrence D'Anna   void log(llvm::raw_ostream &OS) const override;
682085328eeSLawrence D'Anna   std::error_code convertToErrorCode() const override;
68304edd189SLawrence D'Anna   bool Matches(PyObject *exc) const;
68404edd189SLawrence D'Anna   std::string ReadBacktrace() const;
685085328eeSLawrence D'Anna };
686085328eeSLawrence D'Anna 
687085328eeSLawrence D'Anna // This extracts the underlying T out of an Expected<T> and returns it.
688085328eeSLawrence D'Anna // If the Expected is an Error instead of a T, that error will be converted
689085328eeSLawrence D'Anna // into a python exception, and this will return a default-constructed T.
690085328eeSLawrence D'Anna //
691085328eeSLawrence D'Anna // This is appropriate for use right at the boundary of python calling into
692085328eeSLawrence D'Anna // C++, such as in a SWIG typemap.   In such a context you should simply
693085328eeSLawrence D'Anna // check if the returned T is valid, and if it is, return a NULL back
694085328eeSLawrence D'Anna // to python.   This will result in the Error being raised as an exception
695085328eeSLawrence D'Anna // from python code's point of view.
696085328eeSLawrence D'Anna //
697085328eeSLawrence D'Anna // For example:
698085328eeSLawrence D'Anna // ```
699085328eeSLawrence D'Anna // Expected<Foo *> efoop = some_cpp_function();
700085328eeSLawrence D'Anna // Foo *foop = unwrapOrSetPythonException(efoop);
701085328eeSLawrence D'Anna // if (!foop)
702085328eeSLawrence D'Anna //    return NULL;
703085328eeSLawrence D'Anna // do_something(*foop);
704085328eeSLawrence D'Anna //
705085328eeSLawrence D'Anna // If the Error returned was itself created because a python exception was
706085328eeSLawrence D'Anna // raised when C++ code called into python, then the original exception
707085328eeSLawrence D'Anna // will be restored.   Otherwise a simple string exception will be raised.
708085328eeSLawrence D'Anna template <typename T> T unwrapOrSetPythonException(llvm::Expected<T> expected) {
709085328eeSLawrence D'Anna   if (expected)
710085328eeSLawrence D'Anna     return expected.get();
711085328eeSLawrence D'Anna   llvm::handleAllErrors(
712085328eeSLawrence D'Anna       expected.takeError(), [](PythonException &E) { E.Restore(); },
713085328eeSLawrence D'Anna       [](const llvm::ErrorInfoBase &E) {
714085328eeSLawrence D'Anna         PyErr_SetString(PyExc_Exception, E.message().c_str());
715085328eeSLawrence D'Anna       });
716085328eeSLawrence D'Anna   return T();
717085328eeSLawrence D'Anna }
718085328eeSLawrence D'Anna 
719722b6189SLawrence D'Anna // This is only here to help incrementally migrate old, exception-unsafe
720722b6189SLawrence D'Anna // code.
721722b6189SLawrence D'Anna template <typename T> T unwrapIgnoringErrors(llvm::Expected<T> expected) {
722722b6189SLawrence D'Anna   if (expected)
723722b6189SLawrence D'Anna     return std::move(expected.get());
724722b6189SLawrence D'Anna   llvm::consumeError(expected.takeError());
725722b6189SLawrence D'Anna   return T();
726722b6189SLawrence D'Anna }
727722b6189SLawrence D'Anna 
72804edd189SLawrence D'Anna llvm::Expected<PythonObject> runStringOneLine(const llvm::Twine &string,
72904edd189SLawrence D'Anna                                               const PythonDictionary &globals,
73004edd189SLawrence D'Anna                                               const PythonDictionary &locals);
73104edd189SLawrence D'Anna 
73204edd189SLawrence D'Anna llvm::Expected<PythonObject> runStringMultiLine(const llvm::Twine &string,
73304edd189SLawrence D'Anna                                                 const PythonDictionary &globals,
73404edd189SLawrence D'Anna                                                 const PythonDictionary &locals);
73504edd189SLawrence D'Anna 
73604edd189SLawrence D'Anna // Sometimes the best way to interact with a python interpreter is
73704edd189SLawrence D'Anna // to run some python code.   You construct a PythonScript with
73804edd189SLawrence D'Anna // script string.   The script assigns some function to `_function_`
73904edd189SLawrence D'Anna // and you get a C++ callable object that calls the python function.
74004edd189SLawrence D'Anna //
74104edd189SLawrence D'Anna // Example:
74204edd189SLawrence D'Anna //
74304edd189SLawrence D'Anna // const char script[] = R"(
74404edd189SLawrence D'Anna // def main(x, y):
74504edd189SLawrence D'Anna //    ....
74604edd189SLawrence D'Anna // )";
74704edd189SLawrence D'Anna //
74804edd189SLawrence D'Anna // Expected<PythonObject> cpp_foo_wrapper(PythonObject x, PythonObject y) {
74904edd189SLawrence D'Anna //   // no need to synchronize access to this global, we already have the GIL
75004edd189SLawrence D'Anna //   static PythonScript foo(script)
75104edd189SLawrence D'Anna //   return  foo(x, y);
75204edd189SLawrence D'Anna // }
75304edd189SLawrence D'Anna class PythonScript {
75404edd189SLawrence D'Anna   const char *script;
75504edd189SLawrence D'Anna   PythonCallable function;
75604edd189SLawrence D'Anna 
75704edd189SLawrence D'Anna   llvm::Error Init();
75804edd189SLawrence D'Anna 
75904edd189SLawrence D'Anna public:
76004edd189SLawrence D'Anna   PythonScript(const char *script) : script(script), function() {}
76104edd189SLawrence D'Anna 
76204edd189SLawrence D'Anna   template <typename... Args>
76304edd189SLawrence D'Anna   llvm::Expected<PythonObject> operator()(Args &&... args) {
76404edd189SLawrence D'Anna     if (llvm::Error error = Init())
76504edd189SLawrence D'Anna       return std::move(error);
76604edd189SLawrence D'Anna     return function.Call(std::forward<Args>(args)...);
76704edd189SLawrence D'Anna   }
76804edd189SLawrence D'Anna };
76904edd189SLawrence D'Anna 
77004edd189SLawrence D'Anna } // namespace python
7712c1f46dcSZachary Turner } // namespace lldb_private
7722c1f46dcSZachary Turner 
773a281b42bSZachary Turner #endif
774d68983e3SPavel Labath 
775d68983e3SPavel Labath #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
776