12c1f46dcSZachary Turner //===-- 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 
102c1f46dcSZachary Turner #ifdef LLDB_DISABLE_PYTHON
112c1f46dcSZachary Turner 
122c1f46dcSZachary Turner // Python is disabled in this build
132c1f46dcSZachary Turner 
142c1f46dcSZachary Turner #else
152c1f46dcSZachary Turner 
162c1f46dcSZachary Turner #include "lldb-python.h"
172c1f46dcSZachary Turner #include "PythonDataObjects.h"
182c1f46dcSZachary Turner #include "ScriptInterpreterPython.h"
192c1f46dcSZachary Turner 
202c1f46dcSZachary Turner #include "lldb/Core/Stream.h"
212c1f46dcSZachary Turner #include "lldb/Host/File.h"
222c1f46dcSZachary Turner #include "lldb/Interpreter/ScriptInterpreter.h"
232c1f46dcSZachary Turner 
242c1f46dcSZachary Turner #include <stdio.h>
252c1f46dcSZachary Turner 
262c1f46dcSZachary Turner using namespace lldb_private;
272c1f46dcSZachary Turner using namespace lldb;
282c1f46dcSZachary Turner 
292c1f46dcSZachary Turner void
302c1f46dcSZachary Turner StructuredPythonObject::Dump(Stream &s) const
312c1f46dcSZachary Turner {
322c1f46dcSZachary Turner     s << "Python Obj: 0x" << GetValue();
332c1f46dcSZachary Turner }
342c1f46dcSZachary Turner 
352c1f46dcSZachary Turner //----------------------------------------------------------------------
362c1f46dcSZachary Turner // PythonObject
372c1f46dcSZachary Turner //----------------------------------------------------------------------
382c1f46dcSZachary Turner 
392c1f46dcSZachary Turner void
402c1f46dcSZachary Turner PythonObject::Dump(Stream &strm) const
412c1f46dcSZachary Turner {
422c1f46dcSZachary Turner     if (m_py_obj)
432c1f46dcSZachary Turner     {
442c1f46dcSZachary Turner         FILE *file = ::tmpfile();
452c1f46dcSZachary Turner         if (file)
462c1f46dcSZachary Turner         {
472c1f46dcSZachary Turner             ::PyObject_Print (m_py_obj, file, 0);
482c1f46dcSZachary Turner             const long length = ftell (file);
492c1f46dcSZachary Turner             if (length)
502c1f46dcSZachary Turner             {
512c1f46dcSZachary Turner                 ::rewind(file);
522c1f46dcSZachary Turner                 std::vector<char> file_contents (length,'\0');
532c1f46dcSZachary Turner                 const size_t length_read = ::fread (file_contents.data(), 1, file_contents.size(), file);
542c1f46dcSZachary Turner                 if (length_read > 0)
552c1f46dcSZachary Turner                     strm.Write (file_contents.data(), length_read);
562c1f46dcSZachary Turner             }
572c1f46dcSZachary Turner             ::fclose (file);
582c1f46dcSZachary Turner         }
592c1f46dcSZachary Turner     }
602c1f46dcSZachary Turner     else
612c1f46dcSZachary Turner         strm.PutCString ("NULL");
622c1f46dcSZachary Turner }
632c1f46dcSZachary Turner 
642c1f46dcSZachary Turner PyObjectType
652c1f46dcSZachary Turner PythonObject::GetObjectType() const
662c1f46dcSZachary Turner {
67f8b22f8fSZachary Turner     if (!IsAllocated())
682c1f46dcSZachary Turner         return PyObjectType::None;
692c1f46dcSZachary Turner 
707841efbbSZachary Turner     if (PythonModule::Check(m_py_obj))
717841efbbSZachary Turner         return PyObjectType::Module;
7218426935SZachary Turner     if (PythonList::Check(m_py_obj))
732c1f46dcSZachary Turner         return PyObjectType::List;
74a1405147SZachary Turner     if (PythonTuple::Check(m_py_obj))
75a1405147SZachary Turner         return PyObjectType::Tuple;
7618426935SZachary Turner     if (PythonDictionary::Check(m_py_obj))
772c1f46dcSZachary Turner         return PyObjectType::Dictionary;
7818426935SZachary Turner     if (PythonString::Check(m_py_obj))
7922c8efcdSZachary Turner         return PyObjectType::String;
80*5a72c02bSZachary Turner #if PY_MAJOR_VERSION >= 3
81*5a72c02bSZachary Turner     if (PythonBytes::Check(m_py_obj))
82*5a72c02bSZachary Turner         return PyObjectType::Bytes;
83*5a72c02bSZachary Turner #endif
8418426935SZachary Turner     if (PythonInteger::Check(m_py_obj))
8522c8efcdSZachary Turner         return PyObjectType::Integer;
869c40264fSZachary Turner     if (PythonFile::Check(m_py_obj))
879c40264fSZachary Turner         return PyObjectType::File;
88a1405147SZachary Turner     if (PythonCallable::Check(m_py_obj))
89a1405147SZachary Turner         return PyObjectType::Callable;
902c1f46dcSZachary Turner     return PyObjectType::Unknown;
912c1f46dcSZachary Turner }
922c1f46dcSZachary Turner 
932c1f46dcSZachary Turner PythonString
947841efbbSZachary Turner PythonObject::Repr() const
952c1f46dcSZachary Turner {
962c1f46dcSZachary Turner     if (!m_py_obj)
972c1f46dcSZachary Turner         return PythonString();
982c1f46dcSZachary Turner     PyObject *repr = PyObject_Repr(m_py_obj);
992c1f46dcSZachary Turner     if (!repr)
1002c1f46dcSZachary Turner         return PythonString();
101f8b22f8fSZachary Turner     return PythonString(PyRefType::Owned, repr);
1022c1f46dcSZachary Turner }
1032c1f46dcSZachary Turner 
1042c1f46dcSZachary Turner PythonString
1057841efbbSZachary Turner PythonObject::Str() const
1062c1f46dcSZachary Turner {
1072c1f46dcSZachary Turner     if (!m_py_obj)
1082c1f46dcSZachary Turner         return PythonString();
1092c1f46dcSZachary Turner     PyObject *str = PyObject_Str(m_py_obj);
1102c1f46dcSZachary Turner     if (!str)
1112c1f46dcSZachary Turner         return PythonString();
112f8b22f8fSZachary Turner     return PythonString(PyRefType::Owned, str);
1132c1f46dcSZachary Turner }
1142c1f46dcSZachary Turner 
1157841efbbSZachary Turner PythonObject
11602bf92d2SZachary Turner PythonObject::ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict)
1177841efbbSZachary Turner {
118a1405147SZachary Turner     size_t dot_pos = name.find_first_of('.');
119a1405147SZachary Turner     llvm::StringRef piece = name.substr(0, dot_pos);
120a1405147SZachary Turner     PythonObject result = dict.GetItemForKey(PythonString(piece));
121a1405147SZachary Turner     if (dot_pos == llvm::StringRef::npos)
122a1405147SZachary Turner     {
123a1405147SZachary Turner         // There was no dot, we're done.
124a1405147SZachary Turner         return result;
125a1405147SZachary Turner     }
126a1405147SZachary Turner 
127a1405147SZachary Turner     // There was a dot.  The remaining portion of the name should be looked up in
128a1405147SZachary Turner     // the context of the object that was found in the dictionary.
129a1405147SZachary Turner     return result.ResolveName(name.substr(dot_pos + 1));
1307841efbbSZachary Turner }
1317841efbbSZachary Turner 
1327841efbbSZachary Turner PythonObject
1337841efbbSZachary Turner PythonObject::ResolveName(llvm::StringRef name) const
1347841efbbSZachary Turner {
1357841efbbSZachary Turner     // Resolve the name in the context of the specified object.  If,
1367841efbbSZachary Turner     // for example, `this` refers to a PyModule, then this will look for
1377841efbbSZachary Turner     // `name` in this module.  If `this` refers to a PyType, then it will
1387841efbbSZachary Turner     // resolve `name` as an attribute of that type.  If `this` refers to
1397841efbbSZachary Turner     // an instance of an object, then it will resolve `name` as the value
1407841efbbSZachary Turner     // of the specified field.
1417841efbbSZachary Turner     //
1427841efbbSZachary Turner     // This function handles dotted names so that, for example, if `m_py_obj`
1437841efbbSZachary Turner     // refers to the `sys` module, and `name` == "path.append", then it
1447841efbbSZachary Turner     // will find the function `sys.path.append`.
1457841efbbSZachary Turner 
1467841efbbSZachary Turner     size_t dot_pos = name.find_first_of('.');
1477841efbbSZachary Turner     if (dot_pos == llvm::StringRef::npos)
1487841efbbSZachary Turner     {
1497841efbbSZachary Turner         // No dots in the name, we should be able to find the value immediately
150a1405147SZachary Turner         // as an attribute of `m_py_obj`.
1517841efbbSZachary Turner         return GetAttributeValue(name);
1527841efbbSZachary Turner     }
1537841efbbSZachary Turner 
1547841efbbSZachary Turner     // Look up the first piece of the name, and resolve the rest as a child of that.
1557841efbbSZachary Turner     PythonObject parent = ResolveName(name.substr(0, dot_pos));
1567841efbbSZachary Turner     if (!parent.IsAllocated())
1577841efbbSZachary Turner         return PythonObject();
1587841efbbSZachary Turner 
1597841efbbSZachary Turner     // Tail recursion.. should be optimized by the compiler
1607841efbbSZachary Turner     return parent.ResolveName(name.substr(dot_pos + 1));
1617841efbbSZachary Turner }
1627841efbbSZachary Turner 
1632c1f46dcSZachary Turner bool
1649c40264fSZachary Turner PythonObject::HasAttribute(llvm::StringRef attr) const
1659c40264fSZachary Turner {
1669c40264fSZachary Turner     if (!IsValid())
1679c40264fSZachary Turner         return false;
1689c40264fSZachary Turner     PythonString py_attr(attr);
1699c40264fSZachary Turner     return !!PyObject_HasAttr(m_py_obj, py_attr.get());
1709c40264fSZachary Turner }
1719c40264fSZachary Turner 
1727d6d218eSZachary Turner PythonObject
1737d6d218eSZachary Turner PythonObject::GetAttributeValue(llvm::StringRef attr) const
1747d6d218eSZachary Turner {
1757d6d218eSZachary Turner     if (!IsValid())
1767d6d218eSZachary Turner         return PythonObject();
1777d6d218eSZachary Turner 
1787d6d218eSZachary Turner     PythonString py_attr(attr);
1797d6d218eSZachary Turner     if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
1807d6d218eSZachary Turner         return PythonObject();
1817d6d218eSZachary Turner 
1827d6d218eSZachary Turner     return PythonObject(PyRefType::Owned,
1837d6d218eSZachary Turner         PyObject_GetAttr(m_py_obj, py_attr.get()));
1847d6d218eSZachary Turner }
1857d6d218eSZachary Turner 
1869c40264fSZachary Turner bool
187f8b22f8fSZachary Turner PythonObject::IsNone() const
1882c1f46dcSZachary Turner {
189f8b22f8fSZachary Turner     return m_py_obj == Py_None;
190f8b22f8fSZachary Turner }
191f8b22f8fSZachary Turner 
192f8b22f8fSZachary Turner bool
193f8b22f8fSZachary Turner PythonObject::IsValid() const
194f8b22f8fSZachary Turner {
195f8b22f8fSZachary Turner     return m_py_obj != nullptr;
196f8b22f8fSZachary Turner }
197f8b22f8fSZachary Turner 
198f8b22f8fSZachary Turner bool
199f8b22f8fSZachary Turner PythonObject::IsAllocated() const
200f8b22f8fSZachary Turner {
201f8b22f8fSZachary Turner     return IsValid() && !IsNone();
2022c1f46dcSZachary Turner }
2032c1f46dcSZachary Turner 
2042c1f46dcSZachary Turner StructuredData::ObjectSP
2052c1f46dcSZachary Turner PythonObject::CreateStructuredObject() const
2062c1f46dcSZachary Turner {
2072c1f46dcSZachary Turner     switch (GetObjectType())
2082c1f46dcSZachary Turner     {
2092c1f46dcSZachary Turner         case PyObjectType::Dictionary:
210f8b22f8fSZachary Turner             return PythonDictionary(PyRefType::Borrowed, m_py_obj).CreateStructuredDictionary();
2112c1f46dcSZachary Turner         case PyObjectType::Integer:
212f8b22f8fSZachary Turner             return PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger();
2132c1f46dcSZachary Turner         case PyObjectType::List:
214f8b22f8fSZachary Turner             return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
2152c1f46dcSZachary Turner         case PyObjectType::String:
216f8b22f8fSZachary Turner             return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
217*5a72c02bSZachary Turner         case PyObjectType::Bytes:
218*5a72c02bSZachary Turner             return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
2192c1f46dcSZachary Turner         case PyObjectType::None:
2202c1f46dcSZachary Turner             return StructuredData::ObjectSP();
2212c1f46dcSZachary Turner         default:
2222c1f46dcSZachary Turner             return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
2232c1f46dcSZachary Turner     }
2242c1f46dcSZachary Turner }
2252c1f46dcSZachary Turner 
2262c1f46dcSZachary Turner //----------------------------------------------------------------------
2272c1f46dcSZachary Turner // PythonString
2282c1f46dcSZachary Turner //----------------------------------------------------------------------
229*5a72c02bSZachary Turner PythonBytes::PythonBytes() : PythonObject()
230*5a72c02bSZachary Turner {
231*5a72c02bSZachary Turner }
232*5a72c02bSZachary Turner 
233*5a72c02bSZachary Turner PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject()
234*5a72c02bSZachary Turner {
235*5a72c02bSZachary Turner     SetBytes(bytes);
236*5a72c02bSZachary Turner }
237*5a72c02bSZachary Turner 
238*5a72c02bSZachary Turner PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject()
239*5a72c02bSZachary Turner {
240*5a72c02bSZachary Turner     SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
241*5a72c02bSZachary Turner }
242*5a72c02bSZachary Turner 
243*5a72c02bSZachary Turner PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject()
244*5a72c02bSZachary Turner {
245*5a72c02bSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
246*5a72c02bSZachary Turner }
247*5a72c02bSZachary Turner 
248*5a72c02bSZachary Turner PythonBytes::PythonBytes(const PythonBytes &object) : PythonObject(object)
249*5a72c02bSZachary Turner {
250*5a72c02bSZachary Turner }
251*5a72c02bSZachary Turner 
252*5a72c02bSZachary Turner PythonBytes::~PythonBytes()
253*5a72c02bSZachary Turner {
254*5a72c02bSZachary Turner }
255*5a72c02bSZachary Turner 
256*5a72c02bSZachary Turner bool
257*5a72c02bSZachary Turner PythonBytes::Check(PyObject *py_obj)
258*5a72c02bSZachary Turner {
259*5a72c02bSZachary Turner     if (!py_obj)
260*5a72c02bSZachary Turner         return false;
261*5a72c02bSZachary Turner     if (PyBytes_Check(py_obj))
262*5a72c02bSZachary Turner         return true;
263*5a72c02bSZachary Turner     return false;
264*5a72c02bSZachary Turner }
265*5a72c02bSZachary Turner 
266*5a72c02bSZachary Turner void
267*5a72c02bSZachary Turner PythonBytes::Reset(PyRefType type, PyObject *py_obj)
268*5a72c02bSZachary Turner {
269*5a72c02bSZachary Turner     // Grab the desired reference type so that if we end up rejecting
270*5a72c02bSZachary Turner     // `py_obj` it still gets decremented if necessary.
271*5a72c02bSZachary Turner     PythonObject result(type, py_obj);
272*5a72c02bSZachary Turner 
273*5a72c02bSZachary Turner     if (!PythonBytes::Check(py_obj))
274*5a72c02bSZachary Turner     {
275*5a72c02bSZachary Turner         PythonObject::Reset();
276*5a72c02bSZachary Turner         return;
277*5a72c02bSZachary Turner     }
278*5a72c02bSZachary Turner 
279*5a72c02bSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
280*5a72c02bSZachary Turner     // back into the virtual implementation.
281*5a72c02bSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
282*5a72c02bSZachary Turner }
283*5a72c02bSZachary Turner 
284*5a72c02bSZachary Turner llvm::ArrayRef<uint8_t>
285*5a72c02bSZachary Turner PythonBytes::GetBytes() const
286*5a72c02bSZachary Turner {
287*5a72c02bSZachary Turner     if (!IsValid())
288*5a72c02bSZachary Turner         return llvm::ArrayRef<uint8_t>();
289*5a72c02bSZachary Turner 
290*5a72c02bSZachary Turner     Py_ssize_t size;
291*5a72c02bSZachary Turner     char *c;
292*5a72c02bSZachary Turner 
293*5a72c02bSZachary Turner     PyBytes_AsStringAndSize(m_py_obj, &c, &size);
294*5a72c02bSZachary Turner     return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
295*5a72c02bSZachary Turner }
296*5a72c02bSZachary Turner 
297*5a72c02bSZachary Turner size_t
298*5a72c02bSZachary Turner PythonBytes::GetSize() const
299*5a72c02bSZachary Turner {
300*5a72c02bSZachary Turner     if (!IsValid())
301*5a72c02bSZachary Turner         return 0;
302*5a72c02bSZachary Turner     return PyBytes_Size(m_py_obj);
303*5a72c02bSZachary Turner }
304*5a72c02bSZachary Turner 
305*5a72c02bSZachary Turner void
306*5a72c02bSZachary Turner PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes)
307*5a72c02bSZachary Turner {
308*5a72c02bSZachary Turner     const char *data = reinterpret_cast<const char *>(bytes.data());
309*5a72c02bSZachary Turner     PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size());
310*5a72c02bSZachary Turner     PythonObject::Reset(PyRefType::Owned, py_bytes);
311*5a72c02bSZachary Turner }
312*5a72c02bSZachary Turner 
313*5a72c02bSZachary Turner StructuredData::StringSP
314*5a72c02bSZachary Turner PythonBytes::CreateStructuredString() const
315*5a72c02bSZachary Turner {
316*5a72c02bSZachary Turner     StructuredData::StringSP result(new StructuredData::String);
317*5a72c02bSZachary Turner     Py_ssize_t size;
318*5a72c02bSZachary Turner     char *c;
319*5a72c02bSZachary Turner     PyBytes_AsStringAndSize(m_py_obj, &c, &size);
320*5a72c02bSZachary Turner     result->SetValue(std::string(c, size));
321*5a72c02bSZachary Turner     return result;
322*5a72c02bSZachary Turner }
323*5a72c02bSZachary Turner 
324*5a72c02bSZachary Turner //----------------------------------------------------------------------
325*5a72c02bSZachary Turner // PythonString
326*5a72c02bSZachary Turner //----------------------------------------------------------------------
3272c1f46dcSZachary Turner 
328f8b22f8fSZachary Turner PythonString::PythonString(PyRefType type, PyObject *py_obj)
329f8b22f8fSZachary Turner     : PythonObject()
3302c1f46dcSZachary Turner {
331f8b22f8fSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
3322c1f46dcSZachary Turner }
3332c1f46dcSZachary Turner 
334f8b22f8fSZachary Turner PythonString::PythonString(const PythonString &object)
335f8b22f8fSZachary Turner     : PythonObject(object)
3362c1f46dcSZachary Turner {
3372c1f46dcSZachary Turner }
3382c1f46dcSZachary Turner 
33922c8efcdSZachary Turner PythonString::PythonString(llvm::StringRef string)
34022c8efcdSZachary Turner     : PythonObject()
3412c1f46dcSZachary Turner {
34222c8efcdSZachary Turner     SetString(string);
3432c1f46dcSZachary Turner }
3442c1f46dcSZachary Turner 
34522c8efcdSZachary Turner PythonString::PythonString(const char *string)
34622c8efcdSZachary Turner     : PythonObject()
3472c1f46dcSZachary Turner {
34822c8efcdSZachary Turner     SetString(llvm::StringRef(string));
3492c1f46dcSZachary Turner }
3502c1f46dcSZachary Turner 
351f8b22f8fSZachary Turner PythonString::PythonString()
352f8b22f8fSZachary Turner     : PythonObject()
3532c1f46dcSZachary Turner {
3542c1f46dcSZachary Turner }
3552c1f46dcSZachary Turner 
3562c1f46dcSZachary Turner PythonString::~PythonString ()
3572c1f46dcSZachary Turner {
3582c1f46dcSZachary Turner }
3592c1f46dcSZachary Turner 
3602c1f46dcSZachary Turner bool
36122c8efcdSZachary Turner PythonString::Check(PyObject *py_obj)
36222c8efcdSZachary Turner {
36322c8efcdSZachary Turner     if (!py_obj)
36422c8efcdSZachary Turner         return false;
36518426935SZachary Turner 
3667d6d218eSZachary Turner     if (PyUnicode_Check(py_obj))
3677d6d218eSZachary Turner         return true;
3687d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
3697d6d218eSZachary Turner     if (PyString_Check(py_obj))
3707d6d218eSZachary Turner         return true;
37122c8efcdSZachary Turner #endif
3727d6d218eSZachary Turner     return false;
37322c8efcdSZachary Turner }
37422c8efcdSZachary Turner 
375f8b22f8fSZachary Turner void
376f8b22f8fSZachary Turner PythonString::Reset(PyRefType type, PyObject *py_obj)
3772c1f46dcSZachary Turner {
378f8b22f8fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
379f8b22f8fSZachary Turner     // `py_obj` it still gets decremented if necessary.
380f8b22f8fSZachary Turner     PythonObject result(type, py_obj);
381f8b22f8fSZachary Turner 
38222c8efcdSZachary Turner     if (!PythonString::Check(py_obj))
38322c8efcdSZachary Turner     {
384f8b22f8fSZachary Turner         PythonObject::Reset();
385f8b22f8fSZachary Turner         return;
38622c8efcdSZachary Turner     }
3877d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
3887d6d218eSZachary Turner     // In Python 2, Don't store PyUnicode objects directly, because we need
3897d6d218eSZachary Turner     // access to their underlying character buffers which Python 2 doesn't
3907d6d218eSZachary Turner     // provide.
3917d6d218eSZachary Turner     if (PyUnicode_Check(py_obj))
3927d6d218eSZachary Turner         result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get()));
3937d6d218eSZachary Turner #endif
394f8b22f8fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
395f8b22f8fSZachary Turner     // back into the virtual implementation.
396f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
3972c1f46dcSZachary Turner }
3982c1f46dcSZachary Turner 
3992c1f46dcSZachary Turner llvm::StringRef
4002c1f46dcSZachary Turner PythonString::GetString() const
4012c1f46dcSZachary Turner {
40218426935SZachary Turner     if (!IsValid())
40318426935SZachary Turner         return llvm::StringRef();
40418426935SZachary Turner 
40522c8efcdSZachary Turner     Py_ssize_t size;
40622c8efcdSZachary Turner     char *c;
40718426935SZachary Turner 
40818426935SZachary Turner #if PY_MAJOR_VERSION >= 3
40918426935SZachary Turner     c = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
41018426935SZachary Turner #else
41118426935SZachary Turner     PyString_AsStringAndSize(m_py_obj, &c, &size);
41218426935SZachary Turner #endif
41322c8efcdSZachary Turner     return llvm::StringRef(c, size);
41422c8efcdSZachary Turner }
4152c1f46dcSZachary Turner 
4162c1f46dcSZachary Turner size_t
4172c1f46dcSZachary Turner PythonString::GetSize() const
4182c1f46dcSZachary Turner {
419f8b22f8fSZachary Turner     if (IsValid())
42018426935SZachary Turner     {
42118426935SZachary Turner #if PY_MAJOR_VERSION >= 3
42218426935SZachary Turner         return PyUnicode_GetSize(m_py_obj);
42318426935SZachary Turner #else
42418426935SZachary Turner         return PyString_Size(m_py_obj);
42518426935SZachary Turner #endif
42618426935SZachary Turner     }
4272c1f46dcSZachary Turner     return 0;
4282c1f46dcSZachary Turner }
4292c1f46dcSZachary Turner 
4302c1f46dcSZachary Turner void
4312c1f46dcSZachary Turner PythonString::SetString (llvm::StringRef string)
4322c1f46dcSZachary Turner {
43322c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
43422c8efcdSZachary Turner     PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size());
43518426935SZachary Turner     PythonObject::Reset(PyRefType::Owned, unicode);
43622c8efcdSZachary Turner #else
43718426935SZachary Turner     PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
43818426935SZachary Turner     PythonObject::Reset(PyRefType::Owned, str);
43922c8efcdSZachary Turner #endif
4402c1f46dcSZachary Turner }
4412c1f46dcSZachary Turner 
4422c1f46dcSZachary Turner StructuredData::StringSP
4432c1f46dcSZachary Turner PythonString::CreateStructuredString() const
4442c1f46dcSZachary Turner {
4452c1f46dcSZachary Turner     StructuredData::StringSP result(new StructuredData::String);
4462c1f46dcSZachary Turner     result->SetValue(GetString());
4472c1f46dcSZachary Turner     return result;
4482c1f46dcSZachary Turner }
4492c1f46dcSZachary Turner 
4502c1f46dcSZachary Turner //----------------------------------------------------------------------
4512c1f46dcSZachary Turner // PythonInteger
4522c1f46dcSZachary Turner //----------------------------------------------------------------------
4532c1f46dcSZachary Turner 
4547d6d218eSZachary Turner PythonInteger::PythonInteger()
4557d6d218eSZachary Turner     : PythonObject()
4567d6d218eSZachary Turner {
4577d6d218eSZachary Turner 
4587d6d218eSZachary Turner }
4597d6d218eSZachary Turner 
460f8b22f8fSZachary Turner PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj)
461f8b22f8fSZachary Turner     : PythonObject()
4622c1f46dcSZachary Turner {
463f8b22f8fSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type
4642c1f46dcSZachary Turner }
4652c1f46dcSZachary Turner 
466f8b22f8fSZachary Turner PythonInteger::PythonInteger(const PythonInteger &object)
467f8b22f8fSZachary Turner     : PythonObject(object)
4682c1f46dcSZachary Turner {
4692c1f46dcSZachary Turner }
4702c1f46dcSZachary Turner 
471f8b22f8fSZachary Turner PythonInteger::PythonInteger(int64_t value)
472f8b22f8fSZachary Turner     : PythonObject()
4732c1f46dcSZachary Turner {
4742c1f46dcSZachary Turner     SetInteger(value);
4752c1f46dcSZachary Turner }
4762c1f46dcSZachary Turner 
4772c1f46dcSZachary Turner 
4782c1f46dcSZachary Turner PythonInteger::~PythonInteger ()
4792c1f46dcSZachary Turner {
4802c1f46dcSZachary Turner }
4812c1f46dcSZachary Turner 
4822c1f46dcSZachary Turner bool
48322c8efcdSZachary Turner PythonInteger::Check(PyObject *py_obj)
4842c1f46dcSZachary Turner {
48522c8efcdSZachary Turner     if (!py_obj)
48622c8efcdSZachary Turner         return false;
48722c8efcdSZachary Turner 
48822c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
48922c8efcdSZachary Turner     // Python 3 does not have PyInt_Check.  There is only one type of
49022c8efcdSZachary Turner     // integral value, long.
49122c8efcdSZachary Turner     return PyLong_Check(py_obj);
49222c8efcdSZachary Turner #else
49322c8efcdSZachary Turner     return PyLong_Check(py_obj) || PyInt_Check(py_obj);
49422c8efcdSZachary Turner #endif
4952c1f46dcSZachary Turner }
4962c1f46dcSZachary Turner 
497f8b22f8fSZachary Turner void
498f8b22f8fSZachary Turner PythonInteger::Reset(PyRefType type, PyObject *py_obj)
49922c8efcdSZachary Turner {
500f8b22f8fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
501f8b22f8fSZachary Turner     // `py_obj` it still gets decremented if necessary.
502f8b22f8fSZachary Turner     PythonObject result(type, py_obj);
503f8b22f8fSZachary Turner 
50422c8efcdSZachary Turner     if (!PythonInteger::Check(py_obj))
50522c8efcdSZachary Turner     {
506f8b22f8fSZachary Turner         PythonObject::Reset();
507f8b22f8fSZachary Turner         return;
50822c8efcdSZachary Turner     }
50922c8efcdSZachary Turner 
51022c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3
51122c8efcdSZachary Turner     // Always store this as a PyLong, which makes interoperability between
51222c8efcdSZachary Turner     // Python 2.x and Python 3.x easier.  This is only necessary in 2.x,
51322c8efcdSZachary Turner     // since 3.x doesn't even have a PyInt.
51422c8efcdSZachary Turner     if (PyInt_Check(py_obj))
51522c8efcdSZachary Turner     {
516f8b22f8fSZachary Turner         // Since we converted the original object to a different type, the new
517f8b22f8fSZachary Turner         // object is an owned object regardless of the ownership semantics requested
518f8b22f8fSZachary Turner         // by the user.
519f8b22f8fSZachary Turner         result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj)));
52022c8efcdSZachary Turner     }
52122c8efcdSZachary Turner #endif
52222c8efcdSZachary Turner 
523f8b22f8fSZachary Turner     assert(PyLong_Check(result.get()) && "Couldn't get a PyLong from this PyObject");
52422c8efcdSZachary Turner 
525f8b22f8fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
526f8b22f8fSZachary Turner     // back into the virtual implementation.
527f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
5282c1f46dcSZachary Turner }
5292c1f46dcSZachary Turner 
5302c1f46dcSZachary Turner int64_t
5312c1f46dcSZachary Turner PythonInteger::GetInteger() const
5322c1f46dcSZachary Turner {
5332c1f46dcSZachary Turner     if (m_py_obj)
5342c1f46dcSZachary Turner     {
53522c8efcdSZachary Turner         assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
53622c8efcdSZachary Turner 
5372c1f46dcSZachary Turner         return PyLong_AsLongLong(m_py_obj);
5382c1f46dcSZachary Turner     }
5392c1f46dcSZachary Turner     return UINT64_MAX;
5402c1f46dcSZachary Turner }
5412c1f46dcSZachary Turner 
5422c1f46dcSZachary Turner void
5432c1f46dcSZachary Turner PythonInteger::SetInteger(int64_t value)
5442c1f46dcSZachary Turner {
545f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value));
5462c1f46dcSZachary Turner }
5472c1f46dcSZachary Turner 
5482c1f46dcSZachary Turner StructuredData::IntegerSP
5492c1f46dcSZachary Turner PythonInteger::CreateStructuredInteger() const
5502c1f46dcSZachary Turner {
5512c1f46dcSZachary Turner     StructuredData::IntegerSP result(new StructuredData::Integer);
5522c1f46dcSZachary Turner     result->SetValue(GetInteger());
5532c1f46dcSZachary Turner     return result;
5542c1f46dcSZachary Turner }
5552c1f46dcSZachary Turner 
5562c1f46dcSZachary Turner //----------------------------------------------------------------------
5572c1f46dcSZachary Turner // PythonList
5582c1f46dcSZachary Turner //----------------------------------------------------------------------
5592c1f46dcSZachary Turner 
560f8b22f8fSZachary Turner PythonList::PythonList(PyInitialValue value)
561f8b22f8fSZachary Turner     : PythonObject()
5622c1f46dcSZachary Turner {
563f8b22f8fSZachary Turner     if (value == PyInitialValue::Empty)
564f8b22f8fSZachary Turner         Reset(PyRefType::Owned, PyList_New(0));
5652c1f46dcSZachary Turner }
5662c1f46dcSZachary Turner 
56787f47729SZachary Turner PythonList::PythonList(int list_size)
56887f47729SZachary Turner     : PythonObject()
56987f47729SZachary Turner {
57087f47729SZachary Turner     Reset(PyRefType::Owned, PyList_New(list_size));
57187f47729SZachary Turner }
57287f47729SZachary Turner 
573f8b22f8fSZachary Turner PythonList::PythonList(PyRefType type, PyObject *py_obj)
574f8b22f8fSZachary Turner     : PythonObject()
5752c1f46dcSZachary Turner {
576f8b22f8fSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list
5772c1f46dcSZachary Turner }
5782c1f46dcSZachary Turner 
579f8b22f8fSZachary Turner PythonList::PythonList(const PythonList &list)
580f8b22f8fSZachary Turner     : PythonObject(list)
5812c1f46dcSZachary Turner {
5822c1f46dcSZachary Turner }
5832c1f46dcSZachary Turner 
5842c1f46dcSZachary Turner PythonList::~PythonList ()
5852c1f46dcSZachary Turner {
5862c1f46dcSZachary Turner }
5872c1f46dcSZachary Turner 
5882c1f46dcSZachary Turner bool
58922c8efcdSZachary Turner PythonList::Check(PyObject *py_obj)
59022c8efcdSZachary Turner {
59122c8efcdSZachary Turner     if (!py_obj)
59222c8efcdSZachary Turner         return false;
59322c8efcdSZachary Turner     return PyList_Check(py_obj);
59422c8efcdSZachary Turner }
59522c8efcdSZachary Turner 
596f8b22f8fSZachary Turner void
597f8b22f8fSZachary Turner PythonList::Reset(PyRefType type, PyObject *py_obj)
5982c1f46dcSZachary Turner {
599f8b22f8fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
600f8b22f8fSZachary Turner     // `py_obj` it still gets decremented if necessary.
601f8b22f8fSZachary Turner     PythonObject result(type, py_obj);
602f8b22f8fSZachary Turner 
60322c8efcdSZachary Turner     if (!PythonList::Check(py_obj))
60422c8efcdSZachary Turner     {
605f8b22f8fSZachary Turner         PythonObject::Reset();
606f8b22f8fSZachary Turner         return;
60722c8efcdSZachary Turner     }
60822c8efcdSZachary Turner 
609f8b22f8fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
610f8b22f8fSZachary Turner     // back into the virtual implementation.
611f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
6122c1f46dcSZachary Turner }
6132c1f46dcSZachary Turner 
6142c1f46dcSZachary Turner uint32_t
6152c1f46dcSZachary Turner PythonList::GetSize() const
6162c1f46dcSZachary Turner {
617f8b22f8fSZachary Turner     if (IsValid())
6182c1f46dcSZachary Turner         return PyList_GET_SIZE(m_py_obj);
6192c1f46dcSZachary Turner     return 0;
6202c1f46dcSZachary Turner }
6212c1f46dcSZachary Turner 
6222c1f46dcSZachary Turner PythonObject
6232c1f46dcSZachary Turner PythonList::GetItemAtIndex(uint32_t index) const
6242c1f46dcSZachary Turner {
625f8b22f8fSZachary Turner     if (IsValid())
626f8b22f8fSZachary Turner         return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
6272c1f46dcSZachary Turner     return PythonObject();
6282c1f46dcSZachary Turner }
6292c1f46dcSZachary Turner 
6302c1f46dcSZachary Turner void
6312c1f46dcSZachary Turner PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object)
6322c1f46dcSZachary Turner {
633f8b22f8fSZachary Turner     if (IsAllocated() && object.IsValid())
634f8b22f8fSZachary Turner     {
635f8b22f8fSZachary Turner         // PyList_SetItem is documented to "steal" a reference, so we need to
636f8b22f8fSZachary Turner         // convert it to an owned reference by incrementing it.
637f8b22f8fSZachary Turner         Py_INCREF(object.get());
6382c1f46dcSZachary Turner         PyList_SetItem(m_py_obj, index, object.get());
6392c1f46dcSZachary Turner     }
640f8b22f8fSZachary Turner }
6412c1f46dcSZachary Turner 
6422c1f46dcSZachary Turner void
6432c1f46dcSZachary Turner PythonList::AppendItem(const PythonObject &object)
6442c1f46dcSZachary Turner {
645f8b22f8fSZachary Turner     if (IsAllocated() && object.IsValid())
646f8b22f8fSZachary Turner     {
647f8b22f8fSZachary Turner         // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
648f8b22f8fSZachary Turner         // here like we do with `PyList_SetItem`.
6492c1f46dcSZachary Turner         PyList_Append(m_py_obj, object.get());
6502c1f46dcSZachary Turner     }
651f8b22f8fSZachary Turner }
6522c1f46dcSZachary Turner 
6532c1f46dcSZachary Turner StructuredData::ArraySP
6542c1f46dcSZachary Turner PythonList::CreateStructuredArray() const
6552c1f46dcSZachary Turner {
6562c1f46dcSZachary Turner     StructuredData::ArraySP result(new StructuredData::Array);
6572c1f46dcSZachary Turner     uint32_t count = GetSize();
6582c1f46dcSZachary Turner     for (uint32_t i = 0; i < count; ++i)
6592c1f46dcSZachary Turner     {
6602c1f46dcSZachary Turner         PythonObject obj = GetItemAtIndex(i);
6612c1f46dcSZachary Turner         result->AddItem(obj.CreateStructuredObject());
6622c1f46dcSZachary Turner     }
6632c1f46dcSZachary Turner     return result;
6642c1f46dcSZachary Turner }
6652c1f46dcSZachary Turner 
6662c1f46dcSZachary Turner //----------------------------------------------------------------------
667a1405147SZachary Turner // PythonTuple
668a1405147SZachary Turner //----------------------------------------------------------------------
669a1405147SZachary Turner 
670a1405147SZachary Turner PythonTuple::PythonTuple(PyInitialValue value)
671a1405147SZachary Turner     : PythonObject()
672a1405147SZachary Turner {
673a1405147SZachary Turner     if (value == PyInitialValue::Empty)
674a1405147SZachary Turner         Reset(PyRefType::Owned, PyTuple_New(0));
675a1405147SZachary Turner }
676a1405147SZachary Turner 
677a1405147SZachary Turner PythonTuple::PythonTuple(int tuple_size)
678a1405147SZachary Turner     : PythonObject()
679a1405147SZachary Turner {
680a1405147SZachary Turner     Reset(PyRefType::Owned, PyTuple_New(tuple_size));
681a1405147SZachary Turner }
682a1405147SZachary Turner 
683a1405147SZachary Turner PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj)
684a1405147SZachary Turner     : PythonObject()
685a1405147SZachary Turner {
686a1405147SZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple
687a1405147SZachary Turner }
688a1405147SZachary Turner 
689a1405147SZachary Turner PythonTuple::PythonTuple(const PythonTuple &tuple)
690a1405147SZachary Turner     : PythonObject(tuple)
691a1405147SZachary Turner {
692a1405147SZachary Turner }
693a1405147SZachary Turner 
694a1405147SZachary Turner PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects)
695a1405147SZachary Turner {
696a1405147SZachary Turner     m_py_obj = PyTuple_New(objects.size());
697a1405147SZachary Turner 
698a1405147SZachary Turner     uint32_t idx = 0;
699a1405147SZachary Turner     for (auto object : objects)
700a1405147SZachary Turner     {
701a1405147SZachary Turner         if (object.IsValid())
702a1405147SZachary Turner             SetItemAtIndex(idx, object);
703a1405147SZachary Turner         idx++;
704a1405147SZachary Turner     }
705a1405147SZachary Turner }
706a1405147SZachary Turner 
707a1405147SZachary Turner PythonTuple::PythonTuple(std::initializer_list<PyObject*> objects)
708a1405147SZachary Turner {
709a1405147SZachary Turner     m_py_obj = PyTuple_New(objects.size());
710a1405147SZachary Turner 
711a1405147SZachary Turner     uint32_t idx = 0;
712a1405147SZachary Turner     for (auto py_object : objects)
713a1405147SZachary Turner     {
714a1405147SZachary Turner         PythonObject object(PyRefType::Borrowed, py_object);
715a1405147SZachary Turner         if (object.IsValid())
716a1405147SZachary Turner             SetItemAtIndex(idx, object);
717a1405147SZachary Turner         idx++;
718a1405147SZachary Turner     }
719a1405147SZachary Turner }
720a1405147SZachary Turner 
721a1405147SZachary Turner PythonTuple::~PythonTuple()
722a1405147SZachary Turner {
723a1405147SZachary Turner }
724a1405147SZachary Turner 
725a1405147SZachary Turner bool
726a1405147SZachary Turner PythonTuple::Check(PyObject *py_obj)
727a1405147SZachary Turner {
728a1405147SZachary Turner     if (!py_obj)
729a1405147SZachary Turner         return false;
730a1405147SZachary Turner     return PyTuple_Check(py_obj);
731a1405147SZachary Turner }
732a1405147SZachary Turner 
733a1405147SZachary Turner void
734a1405147SZachary Turner PythonTuple::Reset(PyRefType type, PyObject *py_obj)
735a1405147SZachary Turner {
736a1405147SZachary Turner     // Grab the desired reference type so that if we end up rejecting
737a1405147SZachary Turner     // `py_obj` it still gets decremented if necessary.
738a1405147SZachary Turner     PythonObject result(type, py_obj);
739a1405147SZachary Turner 
740a1405147SZachary Turner     if (!PythonTuple::Check(py_obj))
741a1405147SZachary Turner     {
742a1405147SZachary Turner         PythonObject::Reset();
743a1405147SZachary Turner         return;
744a1405147SZachary Turner     }
745a1405147SZachary Turner 
746a1405147SZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
747a1405147SZachary Turner     // back into the virtual implementation.
748a1405147SZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
749a1405147SZachary Turner }
750a1405147SZachary Turner 
751a1405147SZachary Turner uint32_t
752a1405147SZachary Turner PythonTuple::GetSize() const
753a1405147SZachary Turner {
754a1405147SZachary Turner     if (IsValid())
755a1405147SZachary Turner         return PyTuple_GET_SIZE(m_py_obj);
756a1405147SZachary Turner     return 0;
757a1405147SZachary Turner }
758a1405147SZachary Turner 
759a1405147SZachary Turner PythonObject
760a1405147SZachary Turner PythonTuple::GetItemAtIndex(uint32_t index) const
761a1405147SZachary Turner {
762a1405147SZachary Turner     if (IsValid())
763a1405147SZachary Turner         return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
764a1405147SZachary Turner     return PythonObject();
765a1405147SZachary Turner }
766a1405147SZachary Turner 
767a1405147SZachary Turner void
768a1405147SZachary Turner PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object)
769a1405147SZachary Turner {
770a1405147SZachary Turner     if (IsAllocated() && object.IsValid())
771a1405147SZachary Turner     {
772a1405147SZachary Turner         // PyTuple_SetItem is documented to "steal" a reference, so we need to
773a1405147SZachary Turner         // convert it to an owned reference by incrementing it.
774a1405147SZachary Turner         Py_INCREF(object.get());
775a1405147SZachary Turner         PyTuple_SetItem(m_py_obj, index, object.get());
776a1405147SZachary Turner     }
777a1405147SZachary Turner }
778a1405147SZachary Turner 
779a1405147SZachary Turner StructuredData::ArraySP
780a1405147SZachary Turner PythonTuple::CreateStructuredArray() const
781a1405147SZachary Turner {
782a1405147SZachary Turner     StructuredData::ArraySP result(new StructuredData::Array);
783a1405147SZachary Turner     uint32_t count = GetSize();
784a1405147SZachary Turner     for (uint32_t i = 0; i < count; ++i)
785a1405147SZachary Turner     {
786a1405147SZachary Turner         PythonObject obj = GetItemAtIndex(i);
787a1405147SZachary Turner         result->AddItem(obj.CreateStructuredObject());
788a1405147SZachary Turner     }
789a1405147SZachary Turner     return result;
790a1405147SZachary Turner }
791a1405147SZachary Turner 
792a1405147SZachary Turner //----------------------------------------------------------------------
7932c1f46dcSZachary Turner // PythonDictionary
7942c1f46dcSZachary Turner //----------------------------------------------------------------------
7952c1f46dcSZachary Turner 
796f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyInitialValue value)
797f8b22f8fSZachary Turner     : PythonObject()
7982c1f46dcSZachary Turner {
799f8b22f8fSZachary Turner     if (value == PyInitialValue::Empty)
800f8b22f8fSZachary Turner         Reset(PyRefType::Owned, PyDict_New());
8012c1f46dcSZachary Turner }
8022c1f46dcSZachary Turner 
803f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj)
804f8b22f8fSZachary Turner     : PythonObject()
8052c1f46dcSZachary Turner {
806f8b22f8fSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary
8072c1f46dcSZachary Turner }
8082c1f46dcSZachary Turner 
809f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(const PythonDictionary &object)
810f8b22f8fSZachary Turner     : PythonObject(object)
8112c1f46dcSZachary Turner {
8122c1f46dcSZachary Turner }
8132c1f46dcSZachary Turner 
8142c1f46dcSZachary Turner PythonDictionary::~PythonDictionary ()
8152c1f46dcSZachary Turner {
8162c1f46dcSZachary Turner }
8172c1f46dcSZachary Turner 
8182c1f46dcSZachary Turner bool
81922c8efcdSZachary Turner PythonDictionary::Check(PyObject *py_obj)
82022c8efcdSZachary Turner {
82122c8efcdSZachary Turner     if (!py_obj)
82222c8efcdSZachary Turner         return false;
82322c8efcdSZachary Turner 
82422c8efcdSZachary Turner     return PyDict_Check(py_obj);
82522c8efcdSZachary Turner }
82622c8efcdSZachary Turner 
827f8b22f8fSZachary Turner void
828f8b22f8fSZachary Turner PythonDictionary::Reset(PyRefType type, PyObject *py_obj)
8292c1f46dcSZachary Turner {
830f8b22f8fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
831f8b22f8fSZachary Turner     // `py_obj` it still gets decremented if necessary.
832f8b22f8fSZachary Turner     PythonObject result(type, py_obj);
833f8b22f8fSZachary Turner 
83422c8efcdSZachary Turner     if (!PythonDictionary::Check(py_obj))
83522c8efcdSZachary Turner     {
836f8b22f8fSZachary Turner         PythonObject::Reset();
837f8b22f8fSZachary Turner         return;
83822c8efcdSZachary Turner     }
83922c8efcdSZachary Turner 
840f8b22f8fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
841f8b22f8fSZachary Turner     // back into the virtual implementation.
842f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
8432c1f46dcSZachary Turner }
8442c1f46dcSZachary Turner 
8452c1f46dcSZachary Turner uint32_t
8462c1f46dcSZachary Turner PythonDictionary::GetSize() const
8472c1f46dcSZachary Turner {
848f8b22f8fSZachary Turner     if (IsValid())
8492c1f46dcSZachary Turner         return PyDict_Size(m_py_obj);
8502c1f46dcSZachary Turner     return 0;
8512c1f46dcSZachary Turner }
8522c1f46dcSZachary Turner 
8532c1f46dcSZachary Turner PythonList
8542c1f46dcSZachary Turner PythonDictionary::GetKeys() const
8552c1f46dcSZachary Turner {
856f8b22f8fSZachary Turner     if (IsValid())
857f8b22f8fSZachary Turner         return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
858f8b22f8fSZachary Turner     return PythonList(PyInitialValue::Invalid);
8592c1f46dcSZachary Turner }
8602c1f46dcSZachary Turner 
8612c1f46dcSZachary Turner PythonObject
862f8b22f8fSZachary Turner PythonDictionary::GetItemForKey(const PythonObject &key) const
8632c1f46dcSZachary Turner {
864f8b22f8fSZachary Turner     if (IsAllocated() && key.IsValid())
865f8b22f8fSZachary Turner         return PythonObject(PyRefType::Borrowed, PyDict_GetItem(m_py_obj, key.get()));
8662c1f46dcSZachary Turner     return PythonObject();
8672c1f46dcSZachary Turner }
8682c1f46dcSZachary Turner 
8692c1f46dcSZachary Turner void
870f8b22f8fSZachary Turner PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value)
8712c1f46dcSZachary Turner {
872f8b22f8fSZachary Turner     if (IsAllocated() && key.IsValid() && value.IsValid())
8732c1f46dcSZachary Turner         PyDict_SetItem(m_py_obj, key.get(), value.get());
8742c1f46dcSZachary Turner }
8752c1f46dcSZachary Turner 
8762c1f46dcSZachary Turner StructuredData::DictionarySP
8772c1f46dcSZachary Turner PythonDictionary::CreateStructuredDictionary() const
8782c1f46dcSZachary Turner {
8792c1f46dcSZachary Turner     StructuredData::DictionarySP result(new StructuredData::Dictionary);
8802c1f46dcSZachary Turner     PythonList keys(GetKeys());
8812c1f46dcSZachary Turner     uint32_t num_keys = keys.GetSize();
8822c1f46dcSZachary Turner     for (uint32_t i = 0; i < num_keys; ++i)
8832c1f46dcSZachary Turner     {
8842c1f46dcSZachary Turner         PythonObject key = keys.GetItemAtIndex(i);
8852c1f46dcSZachary Turner         PythonObject value = GetItemForKey(key);
8862c1f46dcSZachary Turner         StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
887f8b22f8fSZachary Turner         result->AddItem(key.Str().GetString(), structured_value);
8882c1f46dcSZachary Turner     }
8892c1f46dcSZachary Turner     return result;
8902c1f46dcSZachary Turner }
8912c1f46dcSZachary Turner 
8927841efbbSZachary Turner PythonModule::PythonModule() : PythonObject()
8937841efbbSZachary Turner {
8947841efbbSZachary Turner }
8957841efbbSZachary Turner 
8967841efbbSZachary Turner PythonModule::PythonModule(PyRefType type, PyObject *py_obj)
8977841efbbSZachary Turner {
8987841efbbSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module
8997841efbbSZachary Turner }
9007841efbbSZachary Turner 
9017841efbbSZachary Turner PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict)
9027841efbbSZachary Turner {
9037841efbbSZachary Turner }
9047841efbbSZachary Turner 
9057841efbbSZachary Turner PythonModule::~PythonModule()
9067841efbbSZachary Turner {
9077841efbbSZachary Turner }
9087841efbbSZachary Turner 
9097841efbbSZachary Turner PythonModule
910a1405147SZachary Turner PythonModule::BuiltinsModule()
911a1405147SZachary Turner {
912a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3
913a1405147SZachary Turner     return AddModule("builtins");
914a1405147SZachary Turner #else
915a1405147SZachary Turner     return AddModule("__builtin__");
916a1405147SZachary Turner #endif
917a1405147SZachary Turner }
918a1405147SZachary Turner 
919a1405147SZachary Turner PythonModule
9207841efbbSZachary Turner PythonModule::MainModule()
9217841efbbSZachary Turner {
922a1405147SZachary Turner     return AddModule("__main__");
923a1405147SZachary Turner }
924a1405147SZachary Turner 
925a1405147SZachary Turner PythonModule
926a1405147SZachary Turner PythonModule::AddModule(llvm::StringRef module)
927a1405147SZachary Turner {
928a1405147SZachary Turner     std::string str = module.str();
929a1405147SZachary Turner     return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
9307841efbbSZachary Turner }
9317841efbbSZachary Turner 
9322419f1d5SZachary Turner 
9332419f1d5SZachary Turner PythonModule
9342419f1d5SZachary Turner PythonModule::ImportModule(llvm::StringRef module)
9352419f1d5SZachary Turner {
9362419f1d5SZachary Turner     std::string str = module.str();
9372419f1d5SZachary Turner     return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str()));
9382419f1d5SZachary Turner }
9392419f1d5SZachary Turner 
9407841efbbSZachary Turner bool
9417841efbbSZachary Turner PythonModule::Check(PyObject *py_obj)
9427841efbbSZachary Turner {
9437841efbbSZachary Turner     if (!py_obj)
9447841efbbSZachary Turner         return false;
9457841efbbSZachary Turner 
9467841efbbSZachary Turner     return PyModule_Check(py_obj);
9477841efbbSZachary Turner }
9487841efbbSZachary Turner 
9497841efbbSZachary Turner void
9507841efbbSZachary Turner PythonModule::Reset(PyRefType type, PyObject *py_obj)
9517841efbbSZachary Turner {
9527841efbbSZachary Turner     // Grab the desired reference type so that if we end up rejecting
9537841efbbSZachary Turner     // `py_obj` it still gets decremented if necessary.
9547841efbbSZachary Turner     PythonObject result(type, py_obj);
9557841efbbSZachary Turner 
9567841efbbSZachary Turner     if (!PythonModule::Check(py_obj))
9577841efbbSZachary Turner     {
9587841efbbSZachary Turner         PythonObject::Reset();
9597841efbbSZachary Turner         return;
9607841efbbSZachary Turner     }
9617841efbbSZachary Turner 
9627841efbbSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
9637841efbbSZachary Turner     // back into the virtual implementation.
9647841efbbSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
9657841efbbSZachary Turner }
9667841efbbSZachary Turner 
9677841efbbSZachary Turner PythonDictionary
9687841efbbSZachary Turner PythonModule::GetDictionary() const
9697841efbbSZachary Turner {
9707841efbbSZachary Turner     return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj));
9717841efbbSZachary Turner }
9727841efbbSZachary Turner 
973a1405147SZachary Turner PythonCallable::PythonCallable() : PythonObject()
974a1405147SZachary Turner {
975a1405147SZachary Turner }
976a1405147SZachary Turner 
977a1405147SZachary Turner PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj)
978a1405147SZachary Turner {
979a1405147SZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable
980a1405147SZachary Turner }
981a1405147SZachary Turner 
982a1405147SZachary Turner PythonCallable::PythonCallable(const PythonCallable &callable)
983a1405147SZachary Turner     : PythonObject(callable)
984a1405147SZachary Turner {
985a1405147SZachary Turner }
986a1405147SZachary Turner 
987a1405147SZachary Turner PythonCallable::~PythonCallable()
988a1405147SZachary Turner {
989a1405147SZachary Turner }
990a1405147SZachary Turner 
991a1405147SZachary Turner bool
992a1405147SZachary Turner PythonCallable::Check(PyObject *py_obj)
993a1405147SZachary Turner {
994a1405147SZachary Turner     if (!py_obj)
995a1405147SZachary Turner         return false;
996a1405147SZachary Turner 
997a1405147SZachary Turner     return PyCallable_Check(py_obj);
998a1405147SZachary Turner }
999a1405147SZachary Turner 
1000a1405147SZachary Turner void
1001a1405147SZachary Turner PythonCallable::Reset(PyRefType type, PyObject *py_obj)
1002a1405147SZachary Turner {
1003a1405147SZachary Turner     // Grab the desired reference type so that if we end up rejecting
1004a1405147SZachary Turner     // `py_obj` it still gets decremented if necessary.
1005a1405147SZachary Turner     PythonObject result(type, py_obj);
1006a1405147SZachary Turner 
1007a1405147SZachary Turner     if (!PythonCallable::Check(py_obj))
1008a1405147SZachary Turner     {
1009a1405147SZachary Turner         PythonObject::Reset();
1010a1405147SZachary Turner         return;
1011a1405147SZachary Turner     }
1012a1405147SZachary Turner 
1013a1405147SZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
1014a1405147SZachary Turner     // back into the virtual implementation.
1015a1405147SZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
1016a1405147SZachary Turner }
1017a1405147SZachary Turner 
1018a1405147SZachary Turner 
1019b58fb2f4SZachary Turner PythonCallable::ArgInfo
1020b58fb2f4SZachary Turner PythonCallable::GetNumArguments() const
1021a1405147SZachary Turner {
1022b58fb2f4SZachary Turner     ArgInfo result = { 0, false, false };
1023a1405147SZachary Turner     if (!IsValid())
1024b58fb2f4SZachary Turner         return result;
1025a1405147SZachary Turner 
1026a1405147SZachary Turner     PyObject *py_func_obj = m_py_obj;
1027a1405147SZachary Turner     if (PyMethod_Check(py_func_obj))
1028a1405147SZachary Turner         py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
1029a1405147SZachary Turner 
1030a1405147SZachary Turner     if (!py_func_obj)
1031b58fb2f4SZachary Turner         return result;
1032a1405147SZachary Turner 
1033a1405147SZachary Turner     PyCodeObject* code = (PyCodeObject*)PyFunction_GET_CODE(py_func_obj);
1034a1405147SZachary Turner     if (!code)
1035b58fb2f4SZachary Turner         return result;
1036a1405147SZachary Turner 
1037b58fb2f4SZachary Turner     result.count = code->co_argcount;
1038b58fb2f4SZachary Turner     result.has_varargs = !!(code->co_flags & CO_VARARGS);
1039b58fb2f4SZachary Turner     result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS);
1040b58fb2f4SZachary Turner     return result;
1041b58fb2f4SZachary Turner }
1042b58fb2f4SZachary Turner 
1043b58fb2f4SZachary Turner PythonObject
1044b58fb2f4SZachary Turner PythonCallable::operator ()()
1045b58fb2f4SZachary Turner {
1046b58fb2f4SZachary Turner     return PythonObject(PyRefType::Owned,
1047b58fb2f4SZachary Turner         PyObject_CallObject(m_py_obj, nullptr));
1048a1405147SZachary Turner }
1049a1405147SZachary Turner 
1050a1405147SZachary Turner PythonObject
1051a1405147SZachary Turner PythonCallable::operator ()(std::initializer_list<PyObject*> args)
1052a1405147SZachary Turner {
1053a1405147SZachary Turner     PythonTuple arg_tuple(args);
1054a1405147SZachary Turner     return PythonObject(PyRefType::Owned,
1055a1405147SZachary Turner         PyObject_CallObject(m_py_obj, arg_tuple.get()));
1056a1405147SZachary Turner }
1057a1405147SZachary Turner 
1058a1405147SZachary Turner PythonObject
1059a1405147SZachary Turner PythonCallable::operator ()(std::initializer_list<PythonObject> args)
1060a1405147SZachary Turner {
1061a1405147SZachary Turner     PythonTuple arg_tuple(args);
1062a1405147SZachary Turner     return PythonObject(PyRefType::Owned,
1063a1405147SZachary Turner         PyObject_CallObject(m_py_obj, arg_tuple.get()));
1064a1405147SZachary Turner }
1065a1405147SZachary Turner 
106632064024SZachary Turner PythonFile::PythonFile()
106732064024SZachary Turner     : PythonObject()
106832064024SZachary Turner {
106932064024SZachary Turner }
107032064024SZachary Turner 
10719c40264fSZachary Turner PythonFile::PythonFile(File &file, const char *mode)
10729c40264fSZachary Turner {
10739c40264fSZachary Turner     Reset(file, mode);
10749c40264fSZachary Turner }
10759c40264fSZachary Turner 
1076eda01c31SZachary Turner PythonFile::PythonFile(const char *path, const char *mode)
1077eda01c31SZachary Turner {
1078eda01c31SZachary Turner     FILE *fp = nullptr;
1079eda01c31SZachary Turner     fp = fopen(path, mode);
1080eda01c31SZachary Turner     lldb_private::File file(fp, true);
1081eda01c31SZachary Turner     Reset(file, mode);
1082eda01c31SZachary Turner }
1083eda01c31SZachary Turner 
10849c40264fSZachary Turner PythonFile::PythonFile(PyRefType type, PyObject *o)
10859c40264fSZachary Turner {
10869c40264fSZachary Turner     Reset(type, o);
10879c40264fSZachary Turner }
10889c40264fSZachary Turner 
10899c40264fSZachary Turner PythonFile::~PythonFile()
10909c40264fSZachary Turner {
10919c40264fSZachary Turner }
10929c40264fSZachary Turner 
10939c40264fSZachary Turner bool
10949c40264fSZachary Turner PythonFile::Check(PyObject *py_obj)
10959c40264fSZachary Turner {
10969c40264fSZachary Turner #if PY_MAJOR_VERSION < 3
10979c40264fSZachary Turner     return PyFile_Check(py_obj);
10989c40264fSZachary Turner #else
10999c40264fSZachary Turner     // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
11009c40264fSZachary Turner     // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper
11019c40264fSZachary Turner     // over `io.open()`, which returns some object derived from `io.IOBase`.
11029c40264fSZachary Turner     // As a result, the only way to detect a file in Python 3 is to check whether
11039c40264fSZachary Turner     // it inherits from `io.IOBase`.  Since it is possible for non-files to also
11049c40264fSZachary Turner     // inherit from `io.IOBase`, we additionally verify that it has the `fileno`
11059c40264fSZachary Turner     // attribute, which should guarantee that it is backed by the file system.
11069c40264fSZachary Turner     PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io"));
11079c40264fSZachary Turner     PythonDictionary io_dict(PyRefType::Borrowed, PyModule_GetDict(io_module.get()));
11089c40264fSZachary Turner     PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase"));
11099c40264fSZachary Turner 
11109c40264fSZachary Turner     PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj));
11119c40264fSZachary Turner 
11129c40264fSZachary Turner     if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get()))
11139c40264fSZachary Turner         return false;
11149c40264fSZachary Turner     if (!object_type.HasAttribute("fileno"))
11159c40264fSZachary Turner         return false;
11169c40264fSZachary Turner 
11179c40264fSZachary Turner     return true;
11189c40264fSZachary Turner #endif
11199c40264fSZachary Turner }
11209c40264fSZachary Turner 
11219c40264fSZachary Turner void
11229c40264fSZachary Turner PythonFile::Reset(PyRefType type, PyObject *py_obj)
11239c40264fSZachary Turner {
11249c40264fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
11259c40264fSZachary Turner     // `py_obj` it still gets decremented if necessary.
11269c40264fSZachary Turner     PythonObject result(type, py_obj);
11279c40264fSZachary Turner 
11289c40264fSZachary Turner     if (!PythonFile::Check(py_obj))
11299c40264fSZachary Turner     {
11309c40264fSZachary Turner         PythonObject::Reset();
11319c40264fSZachary Turner         return;
11329c40264fSZachary Turner     }
11339c40264fSZachary Turner 
11349c40264fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack
11359c40264fSZachary Turner     // overflow since it calls back into the virtual implementation.
11369c40264fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
11379c40264fSZachary Turner }
11389c40264fSZachary Turner 
11399c40264fSZachary Turner void
11409c40264fSZachary Turner PythonFile::Reset(File &file, const char *mode)
11419c40264fSZachary Turner {
114232ac147bSZachary Turner     if (!file.IsValid())
114332ac147bSZachary Turner     {
114432ac147bSZachary Turner         Reset();
114532ac147bSZachary Turner         return;
114632ac147bSZachary Turner     }
114732ac147bSZachary Turner 
11489c40264fSZachary Turner     char *cmode = const_cast<char *>(mode);
11499c40264fSZachary Turner #if PY_MAJOR_VERSION >= 3
11509c40264fSZachary Turner     Reset(PyRefType::Owned,
11519c40264fSZachary Turner         PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, -1, nullptr, "ignore", nullptr, 0));
11529c40264fSZachary Turner #else
11539c40264fSZachary Turner     // Read through the Python source, doesn't seem to modify these strings
11549c40264fSZachary Turner     Reset(PyRefType::Owned,
11559c40264fSZachary Turner         PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, nullptr));
11569c40264fSZachary Turner #endif
11579c40264fSZachary Turner }
11589c40264fSZachary Turner 
1159eda01c31SZachary Turner bool
1160eda01c31SZachary Turner PythonFile::GetUnderlyingFile(File &file) const
1161eda01c31SZachary Turner {
1162eda01c31SZachary Turner     if (!IsValid())
1163eda01c31SZachary Turner         return false;
1164eda01c31SZachary Turner 
1165eda01c31SZachary Turner     file.Close();
1166eda01c31SZachary Turner     // We don't own the file descriptor returned by this function, make sure the
1167eda01c31SZachary Turner     // File object knows about that.
1168eda01c31SZachary Turner     file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false);
1169eda01c31SZachary Turner     return file.IsValid();
1170eda01c31SZachary Turner }
1171eda01c31SZachary Turner 
1172eda01c31SZachary Turner 
11732c1f46dcSZachary Turner #endif
1174