499 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			499 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- PythonDataObjects.h--------------------------------------*- C++ -*-===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
 | |
| #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
 | |
| 
 | |
| #ifndef LLDB_DISABLE_PYTHON
 | |
| 
 | |
| // C Includes
 | |
| // C++ Includes
 | |
| // Other libraries and framework includes
 | |
| // Project includes
 | |
| #include "lldb/lldb-defines.h"
 | |
| #include "lldb/Core/ConstString.h"
 | |
| #include "lldb/Core/StructuredData.h"
 | |
| #include "lldb/Core/Flags.h"
 | |
| #include "lldb/Host/File.h"
 | |
| #include "lldb/Interpreter/OptionValue.h"
 | |
| 
 | |
| namespace lldb_private {
 | |
| 
 | |
| class PythonString;
 | |
| class PythonList;
 | |
| class PythonDictionary;
 | |
| class PythonInteger;
 | |
| 
 | |
| class StructuredPythonObject : public StructuredData::Generic
 | |
| {
 | |
| public:
 | |
|     StructuredPythonObject()
 | |
|         : StructuredData::Generic()
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     StructuredPythonObject(void *obj)
 | |
|         : StructuredData::Generic(obj)
 | |
|     {
 | |
|         Py_XINCREF(GetValue());
 | |
|     }
 | |
| 
 | |
|     ~StructuredPythonObject() override
 | |
|     {
 | |
|         if (Py_IsInitialized())
 | |
|             Py_XDECREF(GetValue());
 | |
|         SetValue(nullptr);
 | |
|     }
 | |
| 
 | |
|     bool
 | |
|     IsValid() const override
 | |
|     {
 | |
|         return GetValue() && GetValue() != Py_None;
 | |
|     }
 | |
| 
 | |
|     void Dump(Stream &s) const override;
 | |
| 
 | |
| private:
 | |
|     DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject);
 | |
| };
 | |
| 
 | |
| enum class PyObjectType
 | |
| {
 | |
|     Unknown,
 | |
|     None,
 | |
|     Integer,
 | |
|     Dictionary,
 | |
|     List,
 | |
|     String,
 | |
|     Module,
 | |
|     Callable,
 | |
|     Tuple,
 | |
|     File
 | |
| };
 | |
| 
 | |
| enum class PyRefType
 | |
| {
 | |
|     Borrowed, // We are not given ownership of the incoming PyObject.
 | |
|               // We cannot safely hold it without calling Py_INCREF.
 | |
|     Owned     // We have ownership of the incoming PyObject.  We should
 | |
|               // not call Py_INCREF.
 | |
| };
 | |
| 
 | |
| enum class PyInitialValue
 | |
| {
 | |
|     Invalid,
 | |
|     Empty
 | |
| };
 | |
| 
 | |
| class PythonObject
 | |
| {
 | |
| public:
 | |
|     PythonObject()
 | |
|         : m_py_obj(nullptr)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     PythonObject(PyRefType type, PyObject *py_obj)
 | |
|         : m_py_obj(nullptr)
 | |
|     {
 | |
|         Reset(type, py_obj);
 | |
|     }
 | |
| 
 | |
|     PythonObject(const PythonObject &rhs)
 | |
|         : m_py_obj(nullptr)
 | |
|     {
 | |
|         Reset(rhs);
 | |
|     }
 | |
| 
 | |
|     virtual ~PythonObject()
 | |
|     {
 | |
|         Reset();
 | |
|     }
 | |
| 
 | |
|     void
 | |
|     Reset()
 | |
|     {
 | |
|         // Avoid calling the virtual method since it's not necessary
 | |
|         // to actually validate the type of the PyObject if we're
 | |
|         // just setting to null.
 | |
|         if (Py_IsInitialized())
 | |
|             Py_XDECREF(m_py_obj);
 | |
|         m_py_obj = nullptr;
 | |
|     }
 | |
| 
 | |
|     void
 | |
|     Reset(const PythonObject &rhs)
 | |
|     {
 | |
|         // Avoid calling the virtual method if it's not necessary
 | |
|         // to actually validate the type of the PyObject.
 | |
|         if (!rhs.IsValid())
 | |
|             Reset();
 | |
|         else
 | |
|             Reset(PyRefType::Borrowed, rhs.m_py_obj);
 | |
|     }
 | |
| 
 | |
|     // PythonObject is implicitly convertible to PyObject *, which will call the
 | |
|     // wrong overload.  We want to explicitly disallow this, since a PyObject
 | |
|     // *always* owns its reference.  Therefore the overload which takes a
 | |
|     // PyRefType doesn't make sense, and the copy constructor should be used.
 | |
|     void
 | |
|     Reset(PyRefType type, const PythonObject &ref) = delete;
 | |
| 
 | |
|     virtual void
 | |
|     Reset(PyRefType type, PyObject *py_obj)
 | |
|     {
 | |
|         if (py_obj == m_py_obj)
 | |
|             return;
 | |
| 
 | |
|         if (Py_IsInitialized())
 | |
|             Py_XDECREF(m_py_obj);
 | |
| 
 | |
|         m_py_obj = py_obj;
 | |
| 
 | |
|         // If this is a borrowed reference, we need to convert it to
 | |
|         // an owned reference by incrementing it.  If it is an owned
 | |
|         // reference (for example the caller allocated it with PyDict_New()
 | |
|         // then we must *not* increment it.
 | |
|         if (Py_IsInitialized() && type == PyRefType::Borrowed)
 | |
|             Py_XINCREF(m_py_obj);
 | |
|     }
 | |
|         
 | |
|     void
 | |
|     Dump () const
 | |
|     {
 | |
|         if (m_py_obj)
 | |
|             _PyObject_Dump (m_py_obj);
 | |
|         else
 | |
|             puts ("NULL");
 | |
|     }
 | |
|         
 | |
|     void
 | |
|     Dump (Stream &strm) const;
 | |
| 
 | |
|     PyObject*
 | |
|     get() const
 | |
|     {
 | |
|         return m_py_obj;
 | |
|     }
 | |
| 
 | |
|     PyObject*
 | |
|     release()
 | |
|     {
 | |
|         PyObject *result = m_py_obj;
 | |
|         m_py_obj = nullptr;
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     PythonObject &
 | |
|     operator=(const PythonObject &other)
 | |
|     {
 | |
|         Reset(PyRefType::Borrowed, other.get());
 | |
|         return *this;
 | |
|     }
 | |
| 
 | |
|     PyObjectType
 | |
|     GetObjectType() const;
 | |
| 
 | |
|     PythonString
 | |
|     Repr() const;
 | |
| 
 | |
|     PythonString
 | |
|     Str() const;
 | |
| 
 | |
|     static PythonObject
 | |
|     ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict);
 | |
| 
 | |
|     template<typename T>
 | |
|     static T
 | |
|     ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict)
 | |
|     {
 | |
|         return ResolveNameWithDictionary(name, dict).AsType<T>();
 | |
|     }
 | |
| 
 | |
|     PythonObject
 | |
|     ResolveName(llvm::StringRef name) const;
 | |
| 
 | |
|     template<typename T>
 | |
|     T
 | |
|     ResolveName(llvm::StringRef name) const
 | |
|     {
 | |
|         return ResolveName(name).AsType<T>();
 | |
|     }
 | |
| 
 | |
|     bool
 | |
|     HasAttribute(llvm::StringRef attribute) const;
 | |
| 
 | |
|     PythonObject
 | |
|     GetAttributeValue(llvm::StringRef attribute) const;
 | |
| 
 | |
|     bool
 | |
|     IsValid() const;
 | |
| 
 | |
|     bool
 | |
|     IsAllocated() const;
 | |
| 
 | |
|     bool
 | |
|     IsNone() const;
 | |
| 
 | |
|     template<typename T>
 | |
|     T AsType() const
 | |
|     {
 | |
|         if (!T::Check(m_py_obj))
 | |
|             return T();
 | |
|         return T(PyRefType::Borrowed, m_py_obj);
 | |
|     }
 | |
| 
 | |
|     StructuredData::ObjectSP
 | |
|     CreateStructuredObject() const;
 | |
| 
 | |
| protected:
 | |
|     PyObject* m_py_obj;
 | |
| };
 | |
| 
 | |
| class PythonString : public PythonObject
 | |
| {
 | |
| public:
 | |
|     PythonString();
 | |
|     explicit PythonString(llvm::StringRef string);
 | |
|     explicit PythonString(const char *string);
 | |
|     PythonString(PyRefType type, PyObject *o);
 | |
|     PythonString(const PythonString &object);
 | |
| 
 | |
|     ~PythonString() override;
 | |
| 
 | |
|     static bool Check(PyObject *py_obj);
 | |
| 
 | |
|     // Bring in the no-argument base class version
 | |
|     using PythonObject::Reset;
 | |
| 
 | |
|     void Reset(PyRefType type, PyObject *py_obj) override;
 | |
| 
 | |
|     llvm::StringRef
 | |
|     GetString() const;
 | |
| 
 | |
|     size_t
 | |
|     GetSize() const;
 | |
| 
 | |
|     void SetString(llvm::StringRef string);
 | |
| 
 | |
|     StructuredData::StringSP CreateStructuredString() const;
 | |
| };
 | |
| 
 | |
| class PythonInteger : public PythonObject
 | |
| {
 | |
| public:
 | |
|     PythonInteger();
 | |
|     explicit PythonInteger(int64_t value);
 | |
|     PythonInteger(PyRefType type, PyObject *o);
 | |
|     PythonInteger(const PythonInteger &object);
 | |
| 
 | |
|     ~PythonInteger() override;
 | |
| 
 | |
|     static bool Check(PyObject *py_obj);
 | |
| 
 | |
|     // Bring in the no-argument base class version
 | |
|     using PythonObject::Reset;
 | |
| 
 | |
|     void Reset(PyRefType type, PyObject *py_obj) override;
 | |
| 
 | |
|     int64_t GetInteger() const;
 | |
| 
 | |
|     void
 | |
|     SetInteger (int64_t value);
 | |
| 
 | |
|     StructuredData::IntegerSP CreateStructuredInteger() const;
 | |
| };
 | |
| 
 | |
| class PythonList : public PythonObject
 | |
| {
 | |
| public:
 | |
|     PythonList() {}
 | |
|     explicit PythonList(PyInitialValue value);
 | |
|     explicit PythonList(int list_size);
 | |
|     PythonList(PyRefType type, PyObject *o);
 | |
|     PythonList(const PythonList &list);
 | |
| 
 | |
|     ~PythonList() override;
 | |
| 
 | |
|     static bool Check(PyObject *py_obj);
 | |
| 
 | |
|     // Bring in the no-argument base class version
 | |
|     using PythonObject::Reset;
 | |
| 
 | |
|     void Reset(PyRefType type, PyObject *py_obj) override;
 | |
| 
 | |
|     uint32_t GetSize() const;
 | |
| 
 | |
|     PythonObject GetItemAtIndex(uint32_t index) const;
 | |
| 
 | |
|     void SetItemAtIndex(uint32_t index, const PythonObject &object);
 | |
| 
 | |
|     void AppendItem(const PythonObject &object);
 | |
| 
 | |
|     StructuredData::ArraySP CreateStructuredArray() const;
 | |
| };
 | |
| 
 | |
| class PythonTuple : public PythonObject
 | |
| {
 | |
| public:
 | |
|     PythonTuple() {}
 | |
|     explicit PythonTuple(PyInitialValue value);
 | |
|     explicit PythonTuple(int tuple_size);
 | |
|     PythonTuple(PyRefType type, PyObject *o);
 | |
|     PythonTuple(const PythonTuple &tuple);
 | |
|     PythonTuple(std::initializer_list<PythonObject> objects);
 | |
|     PythonTuple(std::initializer_list<PyObject*> objects);
 | |
| 
 | |
|     ~PythonTuple() override;
 | |
| 
 | |
|     static bool Check(PyObject *py_obj);
 | |
| 
 | |
|     // Bring in the no-argument base class version
 | |
|     using PythonObject::Reset;
 | |
| 
 | |
|     void Reset(PyRefType type, PyObject *py_obj) override;
 | |
| 
 | |
|     uint32_t GetSize() const;
 | |
| 
 | |
|     PythonObject GetItemAtIndex(uint32_t index) const;
 | |
| 
 | |
|     void SetItemAtIndex(uint32_t index, const PythonObject &object);
 | |
| 
 | |
|     StructuredData::ArraySP CreateStructuredArray() const;
 | |
| };
 | |
| 
 | |
| class PythonDictionary : public PythonObject
 | |
| {
 | |
| public:
 | |
|     PythonDictionary() {}
 | |
|     explicit PythonDictionary(PyInitialValue value);
 | |
|     PythonDictionary(PyRefType type, PyObject *o);
 | |
|     PythonDictionary(const PythonDictionary &dict);
 | |
| 
 | |
|     ~PythonDictionary() override;
 | |
| 
 | |
|     static bool Check(PyObject *py_obj);
 | |
| 
 | |
|     // Bring in the no-argument base class version
 | |
|     using PythonObject::Reset;
 | |
| 
 | |
|     void Reset(PyRefType type, PyObject *py_obj) override;
 | |
| 
 | |
|     uint32_t GetSize() const;
 | |
| 
 | |
|     PythonList GetKeys() const;
 | |
| 
 | |
|     PythonObject GetItemForKey(const PythonObject &key) const;
 | |
|     void SetItemForKey(const PythonObject &key, const PythonObject &value);
 | |
| 
 | |
|     StructuredData::DictionarySP CreateStructuredDictionary() const;
 | |
| };
 | |
| 
 | |
| class PythonModule : public PythonObject
 | |
| {
 | |
|   public:
 | |
|     PythonModule();
 | |
|     PythonModule(PyRefType type, PyObject *o);
 | |
|     PythonModule(const PythonModule &dict);
 | |
| 
 | |
|     ~PythonModule() override;
 | |
| 
 | |
|     static bool Check(PyObject *py_obj);
 | |
| 
 | |
|     static PythonModule
 | |
|     BuiltinsModule();
 | |
| 
 | |
|     static PythonModule
 | |
|     MainModule();
 | |
| 
 | |
|     static PythonModule
 | |
|     AddModule(llvm::StringRef module);
 | |
| 
 | |
|     static PythonModule
 | |
|     ImportModule(llvm::StringRef module);
 | |
| 
 | |
|     // Bring in the no-argument base class version
 | |
|     using PythonObject::Reset;
 | |
| 
 | |
|     void Reset(PyRefType type, PyObject *py_obj) override;
 | |
| 
 | |
|     PythonDictionary GetDictionary() const;
 | |
| };
 | |
| 
 | |
| class PythonCallable : public PythonObject
 | |
| {
 | |
| public:
 | |
|     struct ArgInfo {
 | |
|         size_t count;
 | |
|         bool has_varargs : 1;
 | |
|         bool has_kwargs : 1;
 | |
|     };
 | |
| 
 | |
|     PythonCallable();
 | |
|     PythonCallable(PyRefType type, PyObject *o);
 | |
|     PythonCallable(const PythonCallable &dict);
 | |
| 
 | |
|     ~PythonCallable() override;
 | |
| 
 | |
|     static bool
 | |
|     Check(PyObject *py_obj);
 | |
| 
 | |
|     // Bring in the no-argument base class version
 | |
|     using PythonObject::Reset;
 | |
| 
 | |
|     void
 | |
|     Reset(PyRefType type, PyObject *py_obj) override;
 | |
| 
 | |
|     ArgInfo
 | |
|     GetNumArguments() const;
 | |
| 
 | |
|     PythonObject
 | |
|     operator ()();
 | |
| 
 | |
|     PythonObject
 | |
|     operator ()(std::initializer_list<PyObject*> args);
 | |
| 
 | |
|     PythonObject
 | |
|     operator ()(std::initializer_list<PythonObject> args);
 | |
| 
 | |
|     template<typename Arg, typename... Args>
 | |
|     PythonObject
 | |
|     operator ()(const Arg &arg, Args... args)
 | |
|     {
 | |
|         return operator()({ arg, args... });
 | |
|     }
 | |
| };
 | |
| 
 | |
| 
 | |
| class PythonFile : public PythonObject
 | |
| {
 | |
|   public:
 | |
|     PythonFile();
 | |
|     PythonFile(File &file, const char *mode);
 | |
|     PythonFile(const char *path, const char *mode);
 | |
|     PythonFile(PyRefType type, PyObject *o);
 | |
| 
 | |
|     ~PythonFile() override;
 | |
| 
 | |
|     static bool Check(PyObject *py_obj);
 | |
| 
 | |
|     using PythonObject::Reset;
 | |
| 
 | |
|     void Reset(PyRefType type, PyObject *py_obj) override;
 | |
|     void Reset(File &file, const char *mode);
 | |
| 
 | |
|     bool GetUnderlyingFile(File &file) const;
 | |
| };
 | |
| 
 | |
| } // namespace lldb_private
 | |
| 
 | |
| #endif
 | |
| 
 | |
| #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
 |