1bcadb5a3SPavel Labath //===-- PythonDataObjects.cpp -----------------------------------*- C++ -*-===//
22c1f46dcSZachary Turner //
32c1f46dcSZachary Turner //                     The LLVM Compiler Infrastructure
42c1f46dcSZachary Turner //
52c1f46dcSZachary Turner // This file is distributed under the University of Illinois Open Source
62c1f46dcSZachary Turner // License. See LICENSE.TXT for details.
72c1f46dcSZachary Turner //
82c1f46dcSZachary Turner //===----------------------------------------------------------------------===//
92c1f46dcSZachary Turner 
10d68983e3SPavel Labath #ifdef LLDB_DISABLE_PYTHON
11d68983e3SPavel Labath 
12d68983e3SPavel Labath // Python is disabled in this build
13d68983e3SPavel Labath 
14d68983e3SPavel Labath #else
15d68983e3SPavel Labath 
162c1f46dcSZachary Turner #include "PythonDataObjects.h"
172c1f46dcSZachary Turner #include "ScriptInterpreterPython.h"
182c1f46dcSZachary Turner 
192c1f46dcSZachary Turner #include "lldb/Host/File.h"
20190fadcdSZachary Turner #include "lldb/Host/FileSystem.h"
212c1f46dcSZachary Turner #include "lldb/Interpreter/ScriptInterpreter.h"
22bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
232c1f46dcSZachary Turner 
24190fadcdSZachary Turner #include "llvm/Support/ConvertUTF.h"
25190fadcdSZachary Turner 
262c1f46dcSZachary Turner #include <stdio.h>
272c1f46dcSZachary Turner 
28744959b9SEnrico Granata #include "llvm/ADT/StringSwitch.h"
29744959b9SEnrico Granata 
302c1f46dcSZachary Turner using namespace lldb_private;
312c1f46dcSZachary Turner using namespace lldb;
322c1f46dcSZachary Turner 
33b9c1b51eSKate Stone void StructuredPythonObject::Dump(Stream &s, bool pretty_print) const {
342c1f46dcSZachary Turner   s << "Python Obj: 0x" << GetValue();
352c1f46dcSZachary Turner }
362c1f46dcSZachary Turner 
372c1f46dcSZachary Turner //----------------------------------------------------------------------
382c1f46dcSZachary Turner // PythonObject
392c1f46dcSZachary Turner //----------------------------------------------------------------------
402c1f46dcSZachary Turner 
41b9c1b51eSKate Stone void PythonObject::Dump(Stream &strm) const {
42b9c1b51eSKate Stone   if (m_py_obj) {
432c1f46dcSZachary Turner     FILE *file = ::tmpfile();
44b9c1b51eSKate Stone     if (file) {
452c1f46dcSZachary Turner       ::PyObject_Print(m_py_obj, file, 0);
462c1f46dcSZachary Turner       const long length = ftell(file);
47b9c1b51eSKate Stone       if (length) {
482c1f46dcSZachary Turner         ::rewind(file);
492c1f46dcSZachary Turner         std::vector<char> file_contents(length, '\0');
50b9c1b51eSKate Stone         const size_t length_read =
51b9c1b51eSKate Stone             ::fread(file_contents.data(), 1, file_contents.size(), file);
522c1f46dcSZachary Turner         if (length_read > 0)
532c1f46dcSZachary Turner           strm.Write(file_contents.data(), length_read);
542c1f46dcSZachary Turner       }
552c1f46dcSZachary Turner       ::fclose(file);
562c1f46dcSZachary Turner     }
57b9c1b51eSKate Stone   } else
582c1f46dcSZachary Turner     strm.PutCString("NULL");
592c1f46dcSZachary Turner }
602c1f46dcSZachary Turner 
61b9c1b51eSKate Stone PyObjectType PythonObject::GetObjectType() const {
62f8b22f8fSZachary Turner   if (!IsAllocated())
632c1f46dcSZachary Turner     return PyObjectType::None;
642c1f46dcSZachary Turner 
657841efbbSZachary Turner   if (PythonModule::Check(m_py_obj))
667841efbbSZachary Turner     return PyObjectType::Module;
6718426935SZachary Turner   if (PythonList::Check(m_py_obj))
682c1f46dcSZachary Turner     return PyObjectType::List;
69a1405147SZachary Turner   if (PythonTuple::Check(m_py_obj))
70a1405147SZachary Turner     return PyObjectType::Tuple;
7118426935SZachary Turner   if (PythonDictionary::Check(m_py_obj))
722c1f46dcSZachary Turner     return PyObjectType::Dictionary;
7318426935SZachary Turner   if (PythonString::Check(m_py_obj))
7422c8efcdSZachary Turner     return PyObjectType::String;
755a72c02bSZachary Turner #if PY_MAJOR_VERSION >= 3
765a72c02bSZachary Turner   if (PythonBytes::Check(m_py_obj))
775a72c02bSZachary Turner     return PyObjectType::Bytes;
785a72c02bSZachary Turner #endif
79f9d6d204SZachary Turner   if (PythonByteArray::Check(m_py_obj))
80f9d6d204SZachary Turner     return PyObjectType::ByteArray;
8118426935SZachary Turner   if (PythonInteger::Check(m_py_obj))
8222c8efcdSZachary Turner     return PyObjectType::Integer;
839c40264fSZachary Turner   if (PythonFile::Check(m_py_obj))
849c40264fSZachary Turner     return PyObjectType::File;
85a1405147SZachary Turner   if (PythonCallable::Check(m_py_obj))
86a1405147SZachary Turner     return PyObjectType::Callable;
872c1f46dcSZachary Turner   return PyObjectType::Unknown;
882c1f46dcSZachary Turner }
892c1f46dcSZachary Turner 
90b9c1b51eSKate Stone PythonString PythonObject::Repr() const {
912c1f46dcSZachary Turner   if (!m_py_obj)
922c1f46dcSZachary Turner     return PythonString();
932c1f46dcSZachary Turner   PyObject *repr = PyObject_Repr(m_py_obj);
942c1f46dcSZachary Turner   if (!repr)
952c1f46dcSZachary Turner     return PythonString();
96f8b22f8fSZachary Turner   return PythonString(PyRefType::Owned, repr);
972c1f46dcSZachary Turner }
982c1f46dcSZachary Turner 
99b9c1b51eSKate Stone PythonString PythonObject::Str() const {
1002c1f46dcSZachary Turner   if (!m_py_obj)
1012c1f46dcSZachary Turner     return PythonString();
1022c1f46dcSZachary Turner   PyObject *str = PyObject_Str(m_py_obj);
1032c1f46dcSZachary Turner   if (!str)
1042c1f46dcSZachary Turner     return PythonString();
105f8b22f8fSZachary Turner   return PythonString(PyRefType::Owned, str);
1062c1f46dcSZachary Turner }
1072c1f46dcSZachary Turner 
1087841efbbSZachary Turner PythonObject
109b9c1b51eSKate Stone PythonObject::ResolveNameWithDictionary(llvm::StringRef name,
110b9c1b51eSKate Stone                                         const PythonDictionary &dict) {
111a1405147SZachary Turner   size_t dot_pos = name.find_first_of('.');
112a1405147SZachary Turner   llvm::StringRef piece = name.substr(0, dot_pos);
113a1405147SZachary Turner   PythonObject result = dict.GetItemForKey(PythonString(piece));
114b9c1b51eSKate Stone   if (dot_pos == llvm::StringRef::npos) {
115a1405147SZachary Turner     // There was no dot, we're done.
116a1405147SZachary Turner     return result;
117a1405147SZachary Turner   }
118a1405147SZachary Turner 
119a1405147SZachary Turner   // There was a dot.  The remaining portion of the name should be looked up in
120a1405147SZachary Turner   // the context of the object that was found in the dictionary.
121a1405147SZachary Turner   return result.ResolveName(name.substr(dot_pos + 1));
1227841efbbSZachary Turner }
1237841efbbSZachary Turner 
124b9c1b51eSKate Stone PythonObject PythonObject::ResolveName(llvm::StringRef name) const {
12505097246SAdrian Prantl   // Resolve the name in the context of the specified object.  If, for example,
12605097246SAdrian Prantl   // `this` refers to a PyModule, then this will look for `name` in this
12705097246SAdrian Prantl   // module.  If `this` refers to a PyType, then it will resolve `name` as an
12805097246SAdrian Prantl   // attribute of that type.  If `this` refers to an instance of an object,
12905097246SAdrian Prantl   // then it will resolve `name` as the value of the specified field.
1307841efbbSZachary Turner   //
1317841efbbSZachary Turner   // This function handles dotted names so that, for example, if `m_py_obj`
13205097246SAdrian Prantl   // refers to the `sys` module, and `name` == "path.append", then it will find
13305097246SAdrian Prantl   // the function `sys.path.append`.
1347841efbbSZachary Turner 
1357841efbbSZachary Turner   size_t dot_pos = name.find_first_of('.');
136b9c1b51eSKate Stone   if (dot_pos == llvm::StringRef::npos) {
13705097246SAdrian Prantl     // No dots in the name, we should be able to find the value immediately as
13805097246SAdrian Prantl     // an attribute of `m_py_obj`.
1397841efbbSZachary Turner     return GetAttributeValue(name);
1407841efbbSZachary Turner   }
1417841efbbSZachary Turner 
142b9c1b51eSKate Stone   // Look up the first piece of the name, and resolve the rest as a child of
143b9c1b51eSKate Stone   // that.
1447841efbbSZachary Turner   PythonObject parent = ResolveName(name.substr(0, dot_pos));
1457841efbbSZachary Turner   if (!parent.IsAllocated())
1467841efbbSZachary Turner     return PythonObject();
1477841efbbSZachary Turner 
1487841efbbSZachary Turner   // Tail recursion.. should be optimized by the compiler
1497841efbbSZachary Turner   return parent.ResolveName(name.substr(dot_pos + 1));
1507841efbbSZachary Turner }
1517841efbbSZachary Turner 
152b9c1b51eSKate Stone bool PythonObject::HasAttribute(llvm::StringRef attr) const {
1539c40264fSZachary Turner   if (!IsValid())
1549c40264fSZachary Turner     return false;
1559c40264fSZachary Turner   PythonString py_attr(attr);
1569c40264fSZachary Turner   return !!PyObject_HasAttr(m_py_obj, py_attr.get());
1579c40264fSZachary Turner }
1589c40264fSZachary Turner 
159b9c1b51eSKate Stone PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const {
1607d6d218eSZachary Turner   if (!IsValid())
1617d6d218eSZachary Turner     return PythonObject();
1627d6d218eSZachary Turner 
1637d6d218eSZachary Turner   PythonString py_attr(attr);
1647d6d218eSZachary Turner   if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
1657d6d218eSZachary Turner     return PythonObject();
1667d6d218eSZachary Turner 
1677d6d218eSZachary Turner   return PythonObject(PyRefType::Owned,
1687d6d218eSZachary Turner                       PyObject_GetAttr(m_py_obj, py_attr.get()));
1697d6d218eSZachary Turner }
1707d6d218eSZachary Turner 
171b9c1b51eSKate Stone bool PythonObject::IsNone() const { return m_py_obj == Py_None; }
172f8b22f8fSZachary Turner 
173b9c1b51eSKate Stone bool PythonObject::IsValid() const { return m_py_obj != nullptr; }
174f8b22f8fSZachary Turner 
175b9c1b51eSKate Stone bool PythonObject::IsAllocated() const { return IsValid() && !IsNone(); }
1762c1f46dcSZachary Turner 
177b9c1b51eSKate Stone StructuredData::ObjectSP PythonObject::CreateStructuredObject() const {
178b9c1b51eSKate Stone   switch (GetObjectType()) {
1792c1f46dcSZachary Turner   case PyObjectType::Dictionary:
180b9c1b51eSKate Stone     return PythonDictionary(PyRefType::Borrowed, m_py_obj)
181b9c1b51eSKate Stone         .CreateStructuredDictionary();
1822c1f46dcSZachary Turner   case PyObjectType::Integer:
183b9c1b51eSKate Stone     return PythonInteger(PyRefType::Borrowed, m_py_obj)
184b9c1b51eSKate Stone         .CreateStructuredInteger();
1852c1f46dcSZachary Turner   case PyObjectType::List:
186f8b22f8fSZachary Turner     return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
1872c1f46dcSZachary Turner   case PyObjectType::String:
188f8b22f8fSZachary Turner     return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
1895a72c02bSZachary Turner   case PyObjectType::Bytes:
1905a72c02bSZachary Turner     return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
191f9d6d204SZachary Turner   case PyObjectType::ByteArray:
192b9c1b51eSKate Stone     return PythonByteArray(PyRefType::Borrowed, m_py_obj)
193b9c1b51eSKate Stone         .CreateStructuredString();
1942c1f46dcSZachary Turner   case PyObjectType::None:
1952c1f46dcSZachary Turner     return StructuredData::ObjectSP();
1962c1f46dcSZachary Turner   default:
1972c1f46dcSZachary Turner     return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
1982c1f46dcSZachary Turner   }
1992c1f46dcSZachary Turner }
2002c1f46dcSZachary Turner 
2012c1f46dcSZachary Turner //----------------------------------------------------------------------
2022c1f46dcSZachary Turner // PythonString
2032c1f46dcSZachary Turner //----------------------------------------------------------------------
204b9c1b51eSKate Stone PythonBytes::PythonBytes() : PythonObject() {}
2055a72c02bSZachary Turner 
206b9c1b51eSKate Stone PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject() {
2075a72c02bSZachary Turner   SetBytes(bytes);
2085a72c02bSZachary Turner }
2095a72c02bSZachary Turner 
210b9c1b51eSKate Stone PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject() {
2115a72c02bSZachary Turner   SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
2125a72c02bSZachary Turner }
2135a72c02bSZachary Turner 
214b9c1b51eSKate Stone PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject() {
2155a72c02bSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
2165a72c02bSZachary Turner }
2175a72c02bSZachary Turner 
218b9c1b51eSKate Stone PythonBytes::PythonBytes(const PythonBytes &object) : PythonObject(object) {}
2195a72c02bSZachary Turner 
220b9c1b51eSKate Stone PythonBytes::~PythonBytes() {}
2215a72c02bSZachary Turner 
222b9c1b51eSKate Stone bool PythonBytes::Check(PyObject *py_obj) {
2235a72c02bSZachary Turner   if (!py_obj)
2245a72c02bSZachary Turner     return false;
225*a6682a41SJonas Devlieghere   return PyBytes_Check(py_obj);
2265a72c02bSZachary Turner }
2275a72c02bSZachary Turner 
228b9c1b51eSKate Stone void PythonBytes::Reset(PyRefType type, PyObject *py_obj) {
22905097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
23005097246SAdrian Prantl   // still gets decremented if necessary.
2315a72c02bSZachary Turner   PythonObject result(type, py_obj);
2325a72c02bSZachary Turner 
233b9c1b51eSKate Stone   if (!PythonBytes::Check(py_obj)) {
2345a72c02bSZachary Turner     PythonObject::Reset();
2355a72c02bSZachary Turner     return;
2365a72c02bSZachary Turner   }
2375a72c02bSZachary Turner 
238b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
23905097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
2405a72c02bSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
2415a72c02bSZachary Turner }
2425a72c02bSZachary Turner 
243b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const {
2445a72c02bSZachary Turner   if (!IsValid())
2455a72c02bSZachary Turner     return llvm::ArrayRef<uint8_t>();
2465a72c02bSZachary Turner 
2475a72c02bSZachary Turner   Py_ssize_t size;
2485a72c02bSZachary Turner   char *c;
2495a72c02bSZachary Turner 
2505a72c02bSZachary Turner   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
2515a72c02bSZachary Turner   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
2525a72c02bSZachary Turner }
2535a72c02bSZachary Turner 
254b9c1b51eSKate Stone size_t PythonBytes::GetSize() const {
2555a72c02bSZachary Turner   if (!IsValid())
2565a72c02bSZachary Turner     return 0;
2575a72c02bSZachary Turner   return PyBytes_Size(m_py_obj);
2585a72c02bSZachary Turner }
2595a72c02bSZachary Turner 
260b9c1b51eSKate Stone void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) {
2615a72c02bSZachary Turner   const char *data = reinterpret_cast<const char *>(bytes.data());
2625a72c02bSZachary Turner   PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size());
2635a72c02bSZachary Turner   PythonObject::Reset(PyRefType::Owned, py_bytes);
2645a72c02bSZachary Turner }
2655a72c02bSZachary Turner 
266b9c1b51eSKate Stone StructuredData::StringSP PythonBytes::CreateStructuredString() const {
2675a72c02bSZachary Turner   StructuredData::StringSP result(new StructuredData::String);
2685a72c02bSZachary Turner   Py_ssize_t size;
2695a72c02bSZachary Turner   char *c;
2705a72c02bSZachary Turner   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
2715a72c02bSZachary Turner   result->SetValue(std::string(c, size));
2725a72c02bSZachary Turner   return result;
2735a72c02bSZachary Turner }
2745a72c02bSZachary Turner 
275b9c1b51eSKate Stone PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes)
276b9c1b51eSKate Stone     : PythonByteArray(bytes.data(), bytes.size()) {}
277f9d6d204SZachary Turner 
278b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) {
279f9d6d204SZachary Turner   const char *str = reinterpret_cast<const char *>(bytes);
280f9d6d204SZachary Turner   Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length));
281f9d6d204SZachary Turner }
282f9d6d204SZachary Turner 
283b9c1b51eSKate Stone PythonByteArray::PythonByteArray(PyRefType type, PyObject *o) {
284f9d6d204SZachary Turner   Reset(type, o);
285f9d6d204SZachary Turner }
286f9d6d204SZachary Turner 
287b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const PythonBytes &object)
288b9c1b51eSKate Stone     : PythonObject(object) {}
289f9d6d204SZachary Turner 
290b9c1b51eSKate Stone PythonByteArray::~PythonByteArray() {}
291f9d6d204SZachary Turner 
292b9c1b51eSKate Stone bool PythonByteArray::Check(PyObject *py_obj) {
293f9d6d204SZachary Turner   if (!py_obj)
294f9d6d204SZachary Turner     return false;
295*a6682a41SJonas Devlieghere   return PyByteArray_Check(py_obj);
296f9d6d204SZachary Turner }
297f9d6d204SZachary Turner 
298b9c1b51eSKate Stone void PythonByteArray::Reset(PyRefType type, PyObject *py_obj) {
29905097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
30005097246SAdrian Prantl   // still gets decremented if necessary.
301f9d6d204SZachary Turner   PythonObject result(type, py_obj);
302f9d6d204SZachary Turner 
303b9c1b51eSKate Stone   if (!PythonByteArray::Check(py_obj)) {
304f9d6d204SZachary Turner     PythonObject::Reset();
305f9d6d204SZachary Turner     return;
306f9d6d204SZachary Turner   }
307f9d6d204SZachary Turner 
308b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
30905097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
310f9d6d204SZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
311f9d6d204SZachary Turner }
312f9d6d204SZachary Turner 
313b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const {
314f9d6d204SZachary Turner   if (!IsValid())
315f9d6d204SZachary Turner     return llvm::ArrayRef<uint8_t>();
316f9d6d204SZachary Turner 
317f9d6d204SZachary Turner   char *c = PyByteArray_AsString(m_py_obj);
318f9d6d204SZachary Turner   size_t size = GetSize();
319f9d6d204SZachary Turner   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
320f9d6d204SZachary Turner }
321f9d6d204SZachary Turner 
322b9c1b51eSKate Stone size_t PythonByteArray::GetSize() const {
323f9d6d204SZachary Turner   if (!IsValid())
324f9d6d204SZachary Turner     return 0;
325f9d6d204SZachary Turner 
326f9d6d204SZachary Turner   return PyByteArray_Size(m_py_obj);
327f9d6d204SZachary Turner }
328f9d6d204SZachary Turner 
329b9c1b51eSKate Stone StructuredData::StringSP PythonByteArray::CreateStructuredString() const {
330f9d6d204SZachary Turner   StructuredData::StringSP result(new StructuredData::String);
331f9d6d204SZachary Turner   llvm::ArrayRef<uint8_t> bytes = GetBytes();
332f9d6d204SZachary Turner   const char *str = reinterpret_cast<const char *>(bytes.data());
333f9d6d204SZachary Turner   result->SetValue(std::string(str, bytes.size()));
334f9d6d204SZachary Turner   return result;
335f9d6d204SZachary Turner }
336f9d6d204SZachary Turner 
3375a72c02bSZachary Turner //----------------------------------------------------------------------
3385a72c02bSZachary Turner // PythonString
3395a72c02bSZachary Turner //----------------------------------------------------------------------
3402c1f46dcSZachary Turner 
341b9c1b51eSKate Stone PythonString::PythonString(PyRefType type, PyObject *py_obj) : PythonObject() {
342f8b22f8fSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
3432c1f46dcSZachary Turner }
3442c1f46dcSZachary Turner 
345b9c1b51eSKate Stone PythonString::PythonString(const PythonString &object) : PythonObject(object) {}
3462c1f46dcSZachary Turner 
347b9c1b51eSKate Stone PythonString::PythonString(llvm::StringRef string) : PythonObject() {
34822c8efcdSZachary Turner   SetString(string);
3492c1f46dcSZachary Turner }
3502c1f46dcSZachary Turner 
351b9c1b51eSKate Stone PythonString::PythonString(const char *string) : PythonObject() {
35222c8efcdSZachary Turner   SetString(llvm::StringRef(string));
3532c1f46dcSZachary Turner }
3542c1f46dcSZachary Turner 
355b9c1b51eSKate Stone PythonString::PythonString() : PythonObject() {}
3562c1f46dcSZachary Turner 
357b9c1b51eSKate Stone PythonString::~PythonString() {}
3582c1f46dcSZachary Turner 
359b9c1b51eSKate Stone bool PythonString::Check(PyObject *py_obj) {
36022c8efcdSZachary Turner   if (!py_obj)
36122c8efcdSZachary Turner     return false;
36218426935SZachary Turner 
3637d6d218eSZachary Turner   if (PyUnicode_Check(py_obj))
3647d6d218eSZachary Turner     return true;
3657d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
3667d6d218eSZachary Turner   if (PyString_Check(py_obj))
3677d6d218eSZachary Turner     return true;
36822c8efcdSZachary Turner #endif
3697d6d218eSZachary Turner   return false;
37022c8efcdSZachary Turner }
37122c8efcdSZachary Turner 
372b9c1b51eSKate Stone void PythonString::Reset(PyRefType type, PyObject *py_obj) {
37305097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
37405097246SAdrian Prantl   // still gets decremented if necessary.
375f8b22f8fSZachary Turner   PythonObject result(type, py_obj);
376f8b22f8fSZachary Turner 
377b9c1b51eSKate Stone   if (!PythonString::Check(py_obj)) {
378f8b22f8fSZachary Turner     PythonObject::Reset();
379f8b22f8fSZachary Turner     return;
38022c8efcdSZachary Turner   }
3817d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
3827d6d218eSZachary Turner   // In Python 2, Don't store PyUnicode objects directly, because we need
3837d6d218eSZachary Turner   // access to their underlying character buffers which Python 2 doesn't
3847d6d218eSZachary Turner   // provide.
3857d6d218eSZachary Turner   if (PyUnicode_Check(py_obj))
3867d6d218eSZachary Turner     result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get()));
3877d6d218eSZachary Turner #endif
388b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
38905097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
390f8b22f8fSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
3912c1f46dcSZachary Turner }
3922c1f46dcSZachary Turner 
393b9c1b51eSKate Stone llvm::StringRef PythonString::GetString() const {
39418426935SZachary Turner   if (!IsValid())
39518426935SZachary Turner     return llvm::StringRef();
39618426935SZachary Turner 
39722c8efcdSZachary Turner   Py_ssize_t size;
3985457b426SPavel Labath   const char *data;
39918426935SZachary Turner 
40018426935SZachary Turner #if PY_MAJOR_VERSION >= 3
4015457b426SPavel Labath   data = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
40218426935SZachary Turner #else
4035457b426SPavel Labath   char *c;
40418426935SZachary Turner   PyString_AsStringAndSize(m_py_obj, &c, &size);
4055457b426SPavel Labath   data = c;
40618426935SZachary Turner #endif
4075457b426SPavel Labath   return llvm::StringRef(data, size);
40822c8efcdSZachary Turner }
4092c1f46dcSZachary Turner 
410b9c1b51eSKate Stone size_t PythonString::GetSize() const {
411b9c1b51eSKate Stone   if (IsValid()) {
41218426935SZachary Turner #if PY_MAJOR_VERSION >= 3
41318426935SZachary Turner     return PyUnicode_GetSize(m_py_obj);
41418426935SZachary Turner #else
41518426935SZachary Turner     return PyString_Size(m_py_obj);
41618426935SZachary Turner #endif
41718426935SZachary Turner   }
4182c1f46dcSZachary Turner   return 0;
4192c1f46dcSZachary Turner }
4202c1f46dcSZachary Turner 
421b9c1b51eSKate Stone void PythonString::SetString(llvm::StringRef string) {
42222c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
42322c8efcdSZachary Turner   PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size());
42418426935SZachary Turner   PythonObject::Reset(PyRefType::Owned, unicode);
42522c8efcdSZachary Turner #else
42618426935SZachary Turner   PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
42718426935SZachary Turner   PythonObject::Reset(PyRefType::Owned, str);
42822c8efcdSZachary Turner #endif
4292c1f46dcSZachary Turner }
4302c1f46dcSZachary Turner 
431b9c1b51eSKate Stone StructuredData::StringSP PythonString::CreateStructuredString() const {
4322c1f46dcSZachary Turner   StructuredData::StringSP result(new StructuredData::String);
4332c1f46dcSZachary Turner   result->SetValue(GetString());
4342c1f46dcSZachary Turner   return result;
4352c1f46dcSZachary Turner }
4362c1f46dcSZachary Turner 
4372c1f46dcSZachary Turner //----------------------------------------------------------------------
4382c1f46dcSZachary Turner // PythonInteger
4392c1f46dcSZachary Turner //----------------------------------------------------------------------
4402c1f46dcSZachary Turner 
441b9c1b51eSKate Stone PythonInteger::PythonInteger() : PythonObject() {}
4427d6d218eSZachary Turner 
443f8b22f8fSZachary Turner PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj)
444b9c1b51eSKate Stone     : PythonObject() {
445f8b22f8fSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type
4462c1f46dcSZachary Turner }
4472c1f46dcSZachary Turner 
448f8b22f8fSZachary Turner PythonInteger::PythonInteger(const PythonInteger &object)
449b9c1b51eSKate Stone     : PythonObject(object) {}
4502c1f46dcSZachary Turner 
451b9c1b51eSKate Stone PythonInteger::PythonInteger(int64_t value) : PythonObject() {
4522c1f46dcSZachary Turner   SetInteger(value);
4532c1f46dcSZachary Turner }
4542c1f46dcSZachary Turner 
455b9c1b51eSKate Stone PythonInteger::~PythonInteger() {}
4562c1f46dcSZachary Turner 
457b9c1b51eSKate Stone bool PythonInteger::Check(PyObject *py_obj) {
45822c8efcdSZachary Turner   if (!py_obj)
45922c8efcdSZachary Turner     return false;
46022c8efcdSZachary Turner 
46122c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
46205097246SAdrian Prantl   // Python 3 does not have PyInt_Check.  There is only one type of integral
46305097246SAdrian Prantl   // value, long.
46422c8efcdSZachary Turner   return PyLong_Check(py_obj);
46522c8efcdSZachary Turner #else
46622c8efcdSZachary Turner   return PyLong_Check(py_obj) || PyInt_Check(py_obj);
46722c8efcdSZachary Turner #endif
4682c1f46dcSZachary Turner }
4692c1f46dcSZachary Turner 
470b9c1b51eSKate Stone void PythonInteger::Reset(PyRefType type, PyObject *py_obj) {
47105097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
47205097246SAdrian Prantl   // still gets decremented if necessary.
473f8b22f8fSZachary Turner   PythonObject result(type, py_obj);
474f8b22f8fSZachary Turner 
475b9c1b51eSKate Stone   if (!PythonInteger::Check(py_obj)) {
476f8b22f8fSZachary Turner     PythonObject::Reset();
477f8b22f8fSZachary Turner     return;
47822c8efcdSZachary Turner   }
47922c8efcdSZachary Turner 
48022c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3
48105097246SAdrian Prantl   // Always store this as a PyLong, which makes interoperability between Python
48205097246SAdrian Prantl   // 2.x and Python 3.x easier.  This is only necessary in 2.x, since 3.x
48305097246SAdrian Prantl   // doesn't even have a PyInt.
484b9c1b51eSKate Stone   if (PyInt_Check(py_obj)) {
485f8b22f8fSZachary Turner     // Since we converted the original object to a different type, the new
48605097246SAdrian Prantl     // object is an owned object regardless of the ownership semantics
48705097246SAdrian Prantl     // requested by the user.
488f8b22f8fSZachary Turner     result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj)));
48922c8efcdSZachary Turner   }
49022c8efcdSZachary Turner #endif
49122c8efcdSZachary Turner 
492b9c1b51eSKate Stone   assert(PyLong_Check(result.get()) &&
493b9c1b51eSKate Stone          "Couldn't get a PyLong from this PyObject");
49422c8efcdSZachary Turner 
495b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
49605097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
497f8b22f8fSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
4982c1f46dcSZachary Turner }
4992c1f46dcSZachary Turner 
500b9c1b51eSKate Stone int64_t PythonInteger::GetInteger() const {
501b9c1b51eSKate Stone   if (m_py_obj) {
502b9c1b51eSKate Stone     assert(PyLong_Check(m_py_obj) &&
503b9c1b51eSKate Stone            "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
50422c8efcdSZachary Turner 
505008ec446SGreg Clayton     int overflow = 0;
506008ec446SGreg Clayton     int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow);
507b9c1b51eSKate Stone     if (overflow != 0) {
50805097246SAdrian Prantl       // We got an integer that overflows, like 18446744072853913392L we can't
50905097246SAdrian Prantl       // use PyLong_AsLongLong() as it will return 0xffffffffffffffff. If we
51005097246SAdrian Prantl       // use the unsigned long long it will work as expected.
511008ec446SGreg Clayton       const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj);
5124f730dc7SIlia K       result = static_cast<int64_t>(uval);
513008ec446SGreg Clayton     }
514008ec446SGreg Clayton     return result;
5152c1f46dcSZachary Turner   }
5162c1f46dcSZachary Turner   return UINT64_MAX;
5172c1f46dcSZachary Turner }
5182c1f46dcSZachary Turner 
519b9c1b51eSKate Stone void PythonInteger::SetInteger(int64_t value) {
520f8b22f8fSZachary Turner   PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value));
5212c1f46dcSZachary Turner }
5222c1f46dcSZachary Turner 
523b9c1b51eSKate Stone StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const {
5242c1f46dcSZachary Turner   StructuredData::IntegerSP result(new StructuredData::Integer);
5252c1f46dcSZachary Turner   result->SetValue(GetInteger());
5262c1f46dcSZachary Turner   return result;
5272c1f46dcSZachary Turner }
5282c1f46dcSZachary Turner 
5292c1f46dcSZachary Turner //----------------------------------------------------------------------
5302c1f46dcSZachary Turner // PythonList
5312c1f46dcSZachary Turner //----------------------------------------------------------------------
5322c1f46dcSZachary Turner 
533b9c1b51eSKate Stone PythonList::PythonList(PyInitialValue value) : PythonObject() {
534f8b22f8fSZachary Turner   if (value == PyInitialValue::Empty)
535f8b22f8fSZachary Turner     Reset(PyRefType::Owned, PyList_New(0));
5362c1f46dcSZachary Turner }
5372c1f46dcSZachary Turner 
538b9c1b51eSKate Stone PythonList::PythonList(int list_size) : PythonObject() {
53987f47729SZachary Turner   Reset(PyRefType::Owned, PyList_New(list_size));
54087f47729SZachary Turner }
54187f47729SZachary Turner 
542b9c1b51eSKate Stone PythonList::PythonList(PyRefType type, PyObject *py_obj) : PythonObject() {
543f8b22f8fSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list
5442c1f46dcSZachary Turner }
5452c1f46dcSZachary Turner 
546b9c1b51eSKate Stone PythonList::PythonList(const PythonList &list) : PythonObject(list) {}
5472c1f46dcSZachary Turner 
548b9c1b51eSKate Stone PythonList::~PythonList() {}
5492c1f46dcSZachary Turner 
550b9c1b51eSKate Stone bool PythonList::Check(PyObject *py_obj) {
55122c8efcdSZachary Turner   if (!py_obj)
55222c8efcdSZachary Turner     return false;
55322c8efcdSZachary Turner   return PyList_Check(py_obj);
55422c8efcdSZachary Turner }
55522c8efcdSZachary Turner 
556b9c1b51eSKate Stone void PythonList::Reset(PyRefType type, PyObject *py_obj) {
55705097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
55805097246SAdrian Prantl   // still gets decremented if necessary.
559f8b22f8fSZachary Turner   PythonObject result(type, py_obj);
560f8b22f8fSZachary Turner 
561b9c1b51eSKate Stone   if (!PythonList::Check(py_obj)) {
562f8b22f8fSZachary Turner     PythonObject::Reset();
563f8b22f8fSZachary Turner     return;
56422c8efcdSZachary Turner   }
56522c8efcdSZachary Turner 
566b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
56705097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
568f8b22f8fSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
5692c1f46dcSZachary Turner }
5702c1f46dcSZachary Turner 
571b9c1b51eSKate Stone uint32_t PythonList::GetSize() const {
572f8b22f8fSZachary Turner   if (IsValid())
5732c1f46dcSZachary Turner     return PyList_GET_SIZE(m_py_obj);
5742c1f46dcSZachary Turner   return 0;
5752c1f46dcSZachary Turner }
5762c1f46dcSZachary Turner 
577b9c1b51eSKate Stone PythonObject PythonList::GetItemAtIndex(uint32_t index) const {
578f8b22f8fSZachary Turner   if (IsValid())
579f8b22f8fSZachary Turner     return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
5802c1f46dcSZachary Turner   return PythonObject();
5812c1f46dcSZachary Turner }
5822c1f46dcSZachary Turner 
583b9c1b51eSKate Stone void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) {
584b9c1b51eSKate Stone   if (IsAllocated() && object.IsValid()) {
585f8b22f8fSZachary Turner     // PyList_SetItem is documented to "steal" a reference, so we need to
586f8b22f8fSZachary Turner     // convert it to an owned reference by incrementing it.
587f8b22f8fSZachary Turner     Py_INCREF(object.get());
5882c1f46dcSZachary Turner     PyList_SetItem(m_py_obj, index, object.get());
5892c1f46dcSZachary Turner   }
590f8b22f8fSZachary Turner }
5912c1f46dcSZachary Turner 
592b9c1b51eSKate Stone void PythonList::AppendItem(const PythonObject &object) {
593b9c1b51eSKate Stone   if (IsAllocated() && object.IsValid()) {
594f8b22f8fSZachary Turner     // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
595f8b22f8fSZachary Turner     // here like we do with `PyList_SetItem`.
5962c1f46dcSZachary Turner     PyList_Append(m_py_obj, object.get());
5972c1f46dcSZachary Turner   }
598f8b22f8fSZachary Turner }
5992c1f46dcSZachary Turner 
600b9c1b51eSKate Stone StructuredData::ArraySP PythonList::CreateStructuredArray() const {
6012c1f46dcSZachary Turner   StructuredData::ArraySP result(new StructuredData::Array);
6022c1f46dcSZachary Turner   uint32_t count = GetSize();
603b9c1b51eSKate Stone   for (uint32_t i = 0; i < count; ++i) {
6042c1f46dcSZachary Turner     PythonObject obj = GetItemAtIndex(i);
6052c1f46dcSZachary Turner     result->AddItem(obj.CreateStructuredObject());
6062c1f46dcSZachary Turner   }
6072c1f46dcSZachary Turner   return result;
6082c1f46dcSZachary Turner }
6092c1f46dcSZachary Turner 
6102c1f46dcSZachary Turner //----------------------------------------------------------------------
611a1405147SZachary Turner // PythonTuple
612a1405147SZachary Turner //----------------------------------------------------------------------
613a1405147SZachary Turner 
614b9c1b51eSKate Stone PythonTuple::PythonTuple(PyInitialValue value) : PythonObject() {
615a1405147SZachary Turner   if (value == PyInitialValue::Empty)
616a1405147SZachary Turner     Reset(PyRefType::Owned, PyTuple_New(0));
617a1405147SZachary Turner }
618a1405147SZachary Turner 
619b9c1b51eSKate Stone PythonTuple::PythonTuple(int tuple_size) : PythonObject() {
620a1405147SZachary Turner   Reset(PyRefType::Owned, PyTuple_New(tuple_size));
621a1405147SZachary Turner }
622a1405147SZachary Turner 
623b9c1b51eSKate Stone PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj) : PythonObject() {
624a1405147SZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple
625a1405147SZachary Turner }
626a1405147SZachary Turner 
627b9c1b51eSKate Stone PythonTuple::PythonTuple(const PythonTuple &tuple) : PythonObject(tuple) {}
628a1405147SZachary Turner 
629b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) {
630a1405147SZachary Turner   m_py_obj = PyTuple_New(objects.size());
631a1405147SZachary Turner 
632a1405147SZachary Turner   uint32_t idx = 0;
633b9c1b51eSKate Stone   for (auto object : objects) {
634a1405147SZachary Turner     if (object.IsValid())
635a1405147SZachary Turner       SetItemAtIndex(idx, object);
636a1405147SZachary Turner     idx++;
637a1405147SZachary Turner   }
638a1405147SZachary Turner }
639a1405147SZachary Turner 
640b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) {
641a1405147SZachary Turner   m_py_obj = PyTuple_New(objects.size());
642a1405147SZachary Turner 
643a1405147SZachary Turner   uint32_t idx = 0;
644b9c1b51eSKate Stone   for (auto py_object : objects) {
645a1405147SZachary Turner     PythonObject object(PyRefType::Borrowed, py_object);
646a1405147SZachary Turner     if (object.IsValid())
647a1405147SZachary Turner       SetItemAtIndex(idx, object);
648a1405147SZachary Turner     idx++;
649a1405147SZachary Turner   }
650a1405147SZachary Turner }
651a1405147SZachary Turner 
652b9c1b51eSKate Stone PythonTuple::~PythonTuple() {}
653a1405147SZachary Turner 
654b9c1b51eSKate Stone bool PythonTuple::Check(PyObject *py_obj) {
655a1405147SZachary Turner   if (!py_obj)
656a1405147SZachary Turner     return false;
657a1405147SZachary Turner   return PyTuple_Check(py_obj);
658a1405147SZachary Turner }
659a1405147SZachary Turner 
660b9c1b51eSKate Stone void PythonTuple::Reset(PyRefType type, PyObject *py_obj) {
66105097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
66205097246SAdrian Prantl   // still gets decremented if necessary.
663a1405147SZachary Turner   PythonObject result(type, py_obj);
664a1405147SZachary Turner 
665b9c1b51eSKate Stone   if (!PythonTuple::Check(py_obj)) {
666a1405147SZachary Turner     PythonObject::Reset();
667a1405147SZachary Turner     return;
668a1405147SZachary Turner   }
669a1405147SZachary Turner 
670b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
67105097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
672a1405147SZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
673a1405147SZachary Turner }
674a1405147SZachary Turner 
675b9c1b51eSKate Stone uint32_t PythonTuple::GetSize() const {
676a1405147SZachary Turner   if (IsValid())
677a1405147SZachary Turner     return PyTuple_GET_SIZE(m_py_obj);
678a1405147SZachary Turner   return 0;
679a1405147SZachary Turner }
680a1405147SZachary Turner 
681b9c1b51eSKate Stone PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const {
682a1405147SZachary Turner   if (IsValid())
683a1405147SZachary Turner     return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
684a1405147SZachary Turner   return PythonObject();
685a1405147SZachary Turner }
686a1405147SZachary Turner 
687b9c1b51eSKate Stone void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) {
688b9c1b51eSKate Stone   if (IsAllocated() && object.IsValid()) {
689a1405147SZachary Turner     // PyTuple_SetItem is documented to "steal" a reference, so we need to
690a1405147SZachary Turner     // convert it to an owned reference by incrementing it.
691a1405147SZachary Turner     Py_INCREF(object.get());
692a1405147SZachary Turner     PyTuple_SetItem(m_py_obj, index, object.get());
693a1405147SZachary Turner   }
694a1405147SZachary Turner }
695a1405147SZachary Turner 
696b9c1b51eSKate Stone StructuredData::ArraySP PythonTuple::CreateStructuredArray() const {
697a1405147SZachary Turner   StructuredData::ArraySP result(new StructuredData::Array);
698a1405147SZachary Turner   uint32_t count = GetSize();
699b9c1b51eSKate Stone   for (uint32_t i = 0; i < count; ++i) {
700a1405147SZachary Turner     PythonObject obj = GetItemAtIndex(i);
701a1405147SZachary Turner     result->AddItem(obj.CreateStructuredObject());
702a1405147SZachary Turner   }
703a1405147SZachary Turner   return result;
704a1405147SZachary Turner }
705a1405147SZachary Turner 
706a1405147SZachary Turner //----------------------------------------------------------------------
7072c1f46dcSZachary Turner // PythonDictionary
7082c1f46dcSZachary Turner //----------------------------------------------------------------------
7092c1f46dcSZachary Turner 
710b9c1b51eSKate Stone PythonDictionary::PythonDictionary(PyInitialValue value) : PythonObject() {
711f8b22f8fSZachary Turner   if (value == PyInitialValue::Empty)
712f8b22f8fSZachary Turner     Reset(PyRefType::Owned, PyDict_New());
7132c1f46dcSZachary Turner }
7142c1f46dcSZachary Turner 
715f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj)
716b9c1b51eSKate Stone     : PythonObject() {
717f8b22f8fSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary
7182c1f46dcSZachary Turner }
7192c1f46dcSZachary Turner 
720f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(const PythonDictionary &object)
721b9c1b51eSKate Stone     : PythonObject(object) {}
7222c1f46dcSZachary Turner 
723b9c1b51eSKate Stone PythonDictionary::~PythonDictionary() {}
7242c1f46dcSZachary Turner 
725b9c1b51eSKate Stone bool PythonDictionary::Check(PyObject *py_obj) {
72622c8efcdSZachary Turner   if (!py_obj)
72722c8efcdSZachary Turner     return false;
72822c8efcdSZachary Turner 
72922c8efcdSZachary Turner   return PyDict_Check(py_obj);
73022c8efcdSZachary Turner }
73122c8efcdSZachary Turner 
732b9c1b51eSKate Stone void PythonDictionary::Reset(PyRefType type, PyObject *py_obj) {
73305097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
73405097246SAdrian Prantl   // still gets decremented if necessary.
735f8b22f8fSZachary Turner   PythonObject result(type, py_obj);
736f8b22f8fSZachary Turner 
737b9c1b51eSKate Stone   if (!PythonDictionary::Check(py_obj)) {
738f8b22f8fSZachary Turner     PythonObject::Reset();
739f8b22f8fSZachary Turner     return;
74022c8efcdSZachary Turner   }
74122c8efcdSZachary Turner 
742b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
74305097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
744f8b22f8fSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
7452c1f46dcSZachary Turner }
7462c1f46dcSZachary Turner 
747b9c1b51eSKate Stone uint32_t PythonDictionary::GetSize() const {
748f8b22f8fSZachary Turner   if (IsValid())
7492c1f46dcSZachary Turner     return PyDict_Size(m_py_obj);
7502c1f46dcSZachary Turner   return 0;
7512c1f46dcSZachary Turner }
7522c1f46dcSZachary Turner 
753b9c1b51eSKate Stone PythonList PythonDictionary::GetKeys() const {
754f8b22f8fSZachary Turner   if (IsValid())
755f8b22f8fSZachary Turner     return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
756f8b22f8fSZachary Turner   return PythonList(PyInitialValue::Invalid);
7572c1f46dcSZachary Turner }
7582c1f46dcSZachary Turner 
759b9c1b51eSKate Stone PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const {
760f8b22f8fSZachary Turner   if (IsAllocated() && key.IsValid())
761b9c1b51eSKate Stone     return PythonObject(PyRefType::Borrowed,
762b9c1b51eSKate Stone                         PyDict_GetItem(m_py_obj, key.get()));
7632c1f46dcSZachary Turner   return PythonObject();
7642c1f46dcSZachary Turner }
7652c1f46dcSZachary Turner 
766b9c1b51eSKate Stone void PythonDictionary::SetItemForKey(const PythonObject &key,
767b9c1b51eSKate Stone                                      const PythonObject &value) {
768f8b22f8fSZachary Turner   if (IsAllocated() && key.IsValid() && value.IsValid())
7692c1f46dcSZachary Turner     PyDict_SetItem(m_py_obj, key.get(), value.get());
7702c1f46dcSZachary Turner }
7712c1f46dcSZachary Turner 
7722c1f46dcSZachary Turner StructuredData::DictionarySP
773b9c1b51eSKate Stone PythonDictionary::CreateStructuredDictionary() const {
7742c1f46dcSZachary Turner   StructuredData::DictionarySP result(new StructuredData::Dictionary);
7752c1f46dcSZachary Turner   PythonList keys(GetKeys());
7762c1f46dcSZachary Turner   uint32_t num_keys = keys.GetSize();
777b9c1b51eSKate Stone   for (uint32_t i = 0; i < num_keys; ++i) {
7782c1f46dcSZachary Turner     PythonObject key = keys.GetItemAtIndex(i);
7792c1f46dcSZachary Turner     PythonObject value = GetItemForKey(key);
7802c1f46dcSZachary Turner     StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
781f8b22f8fSZachary Turner     result->AddItem(key.Str().GetString(), structured_value);
7822c1f46dcSZachary Turner   }
7832c1f46dcSZachary Turner   return result;
7842c1f46dcSZachary Turner }
7852c1f46dcSZachary Turner 
786b9c1b51eSKate Stone PythonModule::PythonModule() : PythonObject() {}
7877841efbbSZachary Turner 
788b9c1b51eSKate Stone PythonModule::PythonModule(PyRefType type, PyObject *py_obj) {
7897841efbbSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module
7907841efbbSZachary Turner }
7917841efbbSZachary Turner 
792b9c1b51eSKate Stone PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict) {}
7937841efbbSZachary Turner 
794b9c1b51eSKate Stone PythonModule::~PythonModule() {}
7957841efbbSZachary Turner 
796b9c1b51eSKate Stone PythonModule PythonModule::BuiltinsModule() {
797a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3
798a1405147SZachary Turner   return AddModule("builtins");
799a1405147SZachary Turner #else
800a1405147SZachary Turner   return AddModule("__builtin__");
801a1405147SZachary Turner #endif
802a1405147SZachary Turner }
803a1405147SZachary Turner 
804b9c1b51eSKate Stone PythonModule PythonModule::MainModule() { return AddModule("__main__"); }
805a1405147SZachary Turner 
806b9c1b51eSKate Stone PythonModule PythonModule::AddModule(llvm::StringRef module) {
807a1405147SZachary Turner   std::string str = module.str();
808a1405147SZachary Turner   return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
8097841efbbSZachary Turner }
8107841efbbSZachary Turner 
811b9c1b51eSKate Stone PythonModule PythonModule::ImportModule(llvm::StringRef module) {
8122419f1d5SZachary Turner   std::string str = module.str();
8132419f1d5SZachary Turner   return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str()));
8142419f1d5SZachary Turner }
8152419f1d5SZachary Turner 
816b9c1b51eSKate Stone bool PythonModule::Check(PyObject *py_obj) {
8177841efbbSZachary Turner   if (!py_obj)
8187841efbbSZachary Turner     return false;
8197841efbbSZachary Turner 
8207841efbbSZachary Turner   return PyModule_Check(py_obj);
8217841efbbSZachary Turner }
8227841efbbSZachary Turner 
823b9c1b51eSKate Stone void PythonModule::Reset(PyRefType type, PyObject *py_obj) {
82405097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
82505097246SAdrian Prantl   // still gets decremented if necessary.
8267841efbbSZachary Turner   PythonObject result(type, py_obj);
8277841efbbSZachary Turner 
828b9c1b51eSKate Stone   if (!PythonModule::Check(py_obj)) {
8297841efbbSZachary Turner     PythonObject::Reset();
8307841efbbSZachary Turner     return;
8317841efbbSZachary Turner   }
8327841efbbSZachary Turner 
833b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
83405097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
8357841efbbSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
8367841efbbSZachary Turner }
8377841efbbSZachary Turner 
838b9c1b51eSKate Stone PythonDictionary PythonModule::GetDictionary() const {
8397841efbbSZachary Turner   return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj));
8407841efbbSZachary Turner }
8417841efbbSZachary Turner 
842b9c1b51eSKate Stone PythonCallable::PythonCallable() : PythonObject() {}
843a1405147SZachary Turner 
844b9c1b51eSKate Stone PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj) {
845a1405147SZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable
846a1405147SZachary Turner }
847a1405147SZachary Turner 
848a1405147SZachary Turner PythonCallable::PythonCallable(const PythonCallable &callable)
849b9c1b51eSKate Stone     : PythonObject(callable) {}
850a1405147SZachary Turner 
851b9c1b51eSKate Stone PythonCallable::~PythonCallable() {}
852a1405147SZachary Turner 
853b9c1b51eSKate Stone bool PythonCallable::Check(PyObject *py_obj) {
854a1405147SZachary Turner   if (!py_obj)
855a1405147SZachary Turner     return false;
856a1405147SZachary Turner 
857a1405147SZachary Turner   return PyCallable_Check(py_obj);
858a1405147SZachary Turner }
859a1405147SZachary Turner 
860b9c1b51eSKate Stone void PythonCallable::Reset(PyRefType type, PyObject *py_obj) {
86105097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
86205097246SAdrian Prantl   // still gets decremented if necessary.
863a1405147SZachary Turner   PythonObject result(type, py_obj);
864a1405147SZachary Turner 
865b9c1b51eSKate Stone   if (!PythonCallable::Check(py_obj)) {
866a1405147SZachary Turner     PythonObject::Reset();
867a1405147SZachary Turner     return;
868a1405147SZachary Turner   }
869a1405147SZachary Turner 
870b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
87105097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
872a1405147SZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
873a1405147SZachary Turner }
874a1405147SZachary Turner 
875b9c1b51eSKate Stone PythonCallable::ArgInfo PythonCallable::GetNumArguments() const {
876a5d6765cSEnrico Granata   ArgInfo result = {0, false, false, false};
877a1405147SZachary Turner   if (!IsValid())
878b58fb2f4SZachary Turner     return result;
879a1405147SZachary Turner 
880a1405147SZachary Turner   PyObject *py_func_obj = m_py_obj;
881b9c1b51eSKate Stone   if (PyMethod_Check(py_func_obj)) {
882a1405147SZachary Turner     py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
883a5d6765cSEnrico Granata     PythonObject im_self = GetAttributeValue("im_self");
884a5d6765cSEnrico Granata     if (im_self.IsValid() && !im_self.IsNone())
885a5d6765cSEnrico Granata       result.is_bound_method = true;
886b9c1b51eSKate Stone   } else {
887a5d6765cSEnrico Granata     // see if this is a callable object with an __call__ method
888b9c1b51eSKate Stone     if (!PyFunction_Check(py_func_obj)) {
889a5d6765cSEnrico Granata       PythonObject __call__ = GetAttributeValue("__call__");
890b9c1b51eSKate Stone       if (__call__.IsValid()) {
891a5d6765cSEnrico Granata         auto __callable__ = __call__.AsType<PythonCallable>();
892b9c1b51eSKate Stone         if (__callable__.IsValid()) {
893a5d6765cSEnrico Granata           py_func_obj = PyMethod_GET_FUNCTION(__callable__.get());
894a5d6765cSEnrico Granata           PythonObject im_self = GetAttributeValue("im_self");
895a5d6765cSEnrico Granata           if (im_self.IsValid() && !im_self.IsNone())
896a5d6765cSEnrico Granata             result.is_bound_method = true;
897a5d6765cSEnrico Granata         }
898a5d6765cSEnrico Granata       }
899a5d6765cSEnrico Granata     }
900a5d6765cSEnrico Granata   }
901a1405147SZachary Turner 
902a1405147SZachary Turner   if (!py_func_obj)
903b58fb2f4SZachary Turner     return result;
904a1405147SZachary Turner 
905a1405147SZachary Turner   PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj);
906a1405147SZachary Turner   if (!code)
907b58fb2f4SZachary Turner     return result;
908a1405147SZachary Turner 
909b58fb2f4SZachary Turner   result.count = code->co_argcount;
910b58fb2f4SZachary Turner   result.has_varargs = !!(code->co_flags & CO_VARARGS);
911b58fb2f4SZachary Turner   result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS);
912b58fb2f4SZachary Turner   return result;
913b58fb2f4SZachary Turner }
914b58fb2f4SZachary Turner 
915b9c1b51eSKate Stone PythonObject PythonCallable::operator()() {
916b9c1b51eSKate Stone   return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr));
917a1405147SZachary Turner }
918a1405147SZachary Turner 
919b9c1b51eSKate Stone PythonObject PythonCallable::
920b9c1b51eSKate Stone operator()(std::initializer_list<PyObject *> args) {
921a1405147SZachary Turner   PythonTuple arg_tuple(args);
922a1405147SZachary Turner   return PythonObject(PyRefType::Owned,
923a1405147SZachary Turner                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
924a1405147SZachary Turner }
925a1405147SZachary Turner 
926b9c1b51eSKate Stone PythonObject PythonCallable::
927b9c1b51eSKate Stone operator()(std::initializer_list<PythonObject> args) {
928a1405147SZachary Turner   PythonTuple arg_tuple(args);
929a1405147SZachary Turner   return PythonObject(PyRefType::Owned,
930a1405147SZachary Turner                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
931a1405147SZachary Turner }
932a1405147SZachary Turner 
933b9c1b51eSKate Stone PythonFile::PythonFile() : PythonObject() {}
93432064024SZachary Turner 
935b9c1b51eSKate Stone PythonFile::PythonFile(File &file, const char *mode) { Reset(file, mode); }
9369c40264fSZachary Turner 
937b9c1b51eSKate Stone PythonFile::PythonFile(const char *path, const char *mode) {
93850bc1ed2SJonas Devlieghere   lldb_private::File file;
93950bc1ed2SJonas Devlieghere   FileSystem::Instance().Open(file, FileSpec(path), GetOptionsFromMode(mode));
940eda01c31SZachary Turner   Reset(file, mode);
941eda01c31SZachary Turner }
942eda01c31SZachary Turner 
943b9c1b51eSKate Stone PythonFile::PythonFile(PyRefType type, PyObject *o) { Reset(type, o); }
9449c40264fSZachary Turner 
945b9c1b51eSKate Stone PythonFile::~PythonFile() {}
9469c40264fSZachary Turner 
947b9c1b51eSKate Stone bool PythonFile::Check(PyObject *py_obj) {
9489c40264fSZachary Turner #if PY_MAJOR_VERSION < 3
94923502721SJason Molenda   return PyFile_Check(py_obj);
95023502721SJason Molenda #else
9519c40264fSZachary Turner   // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
9529c40264fSZachary Turner   // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper
95305097246SAdrian Prantl   // over `io.open()`, which returns some object derived from `io.IOBase`. As a
95405097246SAdrian Prantl   // result, the only way to detect a file in Python 3 is to check whether it
95505097246SAdrian Prantl   // inherits from `io.IOBase`.  Since it is possible for non-files to also
9569c40264fSZachary Turner   // inherit from `io.IOBase`, we additionally verify that it has the `fileno`
9579c40264fSZachary Turner   // attribute, which should guarantee that it is backed by the file system.
9589c40264fSZachary Turner   PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io"));
959b9c1b51eSKate Stone   PythonDictionary io_dict(PyRefType::Borrowed,
960b9c1b51eSKate Stone                            PyModule_GetDict(io_module.get()));
9619c40264fSZachary Turner   PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase"));
9629c40264fSZachary Turner 
9639c40264fSZachary Turner   PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj));
9649c40264fSZachary Turner 
9659c40264fSZachary Turner   if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get()))
9669c40264fSZachary Turner     return false;
9679c40264fSZachary Turner   if (!object_type.HasAttribute("fileno"))
9689c40264fSZachary Turner     return false;
9699c40264fSZachary Turner 
9709c40264fSZachary Turner   return true;
97123502721SJason Molenda #endif
9729c40264fSZachary Turner }
9739c40264fSZachary Turner 
974b9c1b51eSKate Stone void PythonFile::Reset(PyRefType type, PyObject *py_obj) {
97505097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
97605097246SAdrian Prantl   // still gets decremented if necessary.
9779c40264fSZachary Turner   PythonObject result(type, py_obj);
9789c40264fSZachary Turner 
97923502721SJason Molenda   if (!PythonFile::Check(py_obj)) {
9809c40264fSZachary Turner     PythonObject::Reset();
9819c40264fSZachary Turner     return;
9829c40264fSZachary Turner   }
9839c40264fSZachary Turner 
9849c40264fSZachary Turner   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
9859c40264fSZachary Turner   // overflow since it calls back into the virtual implementation.
9869c40264fSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
9879c40264fSZachary Turner }
9889c40264fSZachary Turner 
989b9c1b51eSKate Stone void PythonFile::Reset(File &file, const char *mode) {
990b9c1b51eSKate Stone   if (!file.IsValid()) {
99132ac147bSZachary Turner     Reset();
99232ac147bSZachary Turner     return;
99332ac147bSZachary Turner   }
99432ac147bSZachary Turner 
9959c40264fSZachary Turner   char *cmode = const_cast<char *>(mode);
9969c40264fSZachary Turner #if PY_MAJOR_VERSION >= 3
997b9c1b51eSKate Stone   Reset(PyRefType::Owned, PyFile_FromFd(file.GetDescriptor(), nullptr, cmode,
998b9c1b51eSKate Stone                                         -1, nullptr, "ignore", nullptr, 0));
9999c40264fSZachary Turner #else
10009c40264fSZachary Turner   // Read through the Python source, doesn't seem to modify these strings
10019c40264fSZachary Turner   Reset(PyRefType::Owned,
1002b9c1b51eSKate Stone         PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode,
1003b9c1b51eSKate Stone                         nullptr));
10049c40264fSZachary Turner #endif
10059c40264fSZachary Turner }
10069c40264fSZachary Turner 
1007b9c1b51eSKate Stone uint32_t PythonFile::GetOptionsFromMode(llvm::StringRef mode) {
1008744959b9SEnrico Granata   if (mode.empty())
1009744959b9SEnrico Granata     return 0;
1010744959b9SEnrico Granata 
1011771ef6d4SMalcolm Parsons   return llvm::StringSwitch<uint32_t>(mode.str())
1012744959b9SEnrico Granata       .Case("r", File::eOpenOptionRead)
1013744959b9SEnrico Granata       .Case("w", File::eOpenOptionWrite)
1014b9c1b51eSKate Stone       .Case("a", File::eOpenOptionWrite | File::eOpenOptionAppend |
1015b9c1b51eSKate Stone                      File::eOpenOptionCanCreate)
1016744959b9SEnrico Granata       .Case("r+", File::eOpenOptionRead | File::eOpenOptionWrite)
1017b9c1b51eSKate Stone       .Case("w+", File::eOpenOptionRead | File::eOpenOptionWrite |
1018b9c1b51eSKate Stone                       File::eOpenOptionCanCreate | File::eOpenOptionTruncate)
1019b9c1b51eSKate Stone       .Case("a+", File::eOpenOptionRead | File::eOpenOptionWrite |
1020b9c1b51eSKate Stone                       File::eOpenOptionAppend | File::eOpenOptionCanCreate)
1021744959b9SEnrico Granata       .Default(0);
1022744959b9SEnrico Granata }
1023744959b9SEnrico Granata 
1024b9c1b51eSKate Stone bool PythonFile::GetUnderlyingFile(File &file) const {
1025eda01c31SZachary Turner   if (!IsValid())
1026eda01c31SZachary Turner     return false;
1027eda01c31SZachary Turner 
1028eda01c31SZachary Turner   file.Close();
1029eda01c31SZachary Turner   // We don't own the file descriptor returned by this function, make sure the
1030eda01c31SZachary Turner   // File object knows about that.
1031eda01c31SZachary Turner   file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false);
1032744959b9SEnrico Granata   PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>();
1033744959b9SEnrico Granata   file.SetOptions(PythonFile::GetOptionsFromMode(py_mode.GetString()));
1034eda01c31SZachary Turner   return file.IsValid();
1035eda01c31SZachary Turner }
1036d68983e3SPavel Labath 
1037d68983e3SPavel Labath #endif
1038