summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/ScriptInterpreter/Python
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2015-11-11 17:59:49 +0000
committerZachary Turner <zturner@google.com>2015-11-11 17:59:49 +0000
commit7841efbb9255126763167b9d7d59242333c6f1bd (patch)
tree772ef04f6ea7c4bf9115b57228f2e8122164b55f /lldb/source/Plugins/ScriptInterpreter/Python
parent7d7814ae8a50999db77c0617989232d807c801a2 (diff)
downloadbcm5719-llvm-7841efbb9255126763167b9d7d59242333c6f1bd.tar.gz
bcm5719-llvm-7841efbb9255126763167b9d7d59242333c6f1bd.zip
Add a `PythonModule` class, and a root-level method for resolving names.
llvm-svn: 252765
Diffstat (limited to 'lldb/source/Plugins/ScriptInterpreter/Python')
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp99
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h49
2 files changed, 136 insertions, 12 deletions
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
index 9efed0ad45a..a621c05338d 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
@@ -67,6 +67,8 @@ PythonObject::GetObjectType() const
if (!IsAllocated())
return PyObjectType::None;
+ if (PythonModule::Check(m_py_obj))
+ return PyObjectType::Module;
if (PythonList::Check(m_py_obj))
return PyObjectType::List;
if (PythonDictionary::Check(m_py_obj))
@@ -81,7 +83,7 @@ PythonObject::GetObjectType() const
}
PythonString
-PythonObject::Repr()
+PythonObject::Repr() const
{
if (!m_py_obj)
return PythonString();
@@ -92,7 +94,7 @@ PythonObject::Repr()
}
PythonString
-PythonObject::Str()
+PythonObject::Str() const
{
if (!m_py_obj)
return PythonString();
@@ -102,6 +104,43 @@ PythonObject::Str()
return PythonString(PyRefType::Owned, str);
}
+PythonObject
+PythonObject::ResolveNameGlobal(llvm::StringRef name)
+{
+ return PythonModule::MainModule().ResolveName(name);
+}
+
+PythonObject
+PythonObject::ResolveName(llvm::StringRef name) const
+{
+ // Resolve the name in the context of the specified object. If,
+ // for example, `this` refers to a PyModule, then this will look for
+ // `name` in this module. If `this` refers to a PyType, then it will
+ // resolve `name` as an attribute of that type. If `this` refers to
+ // an instance of an object, then it will resolve `name` as the value
+ // of the specified field.
+ //
+ // This function handles dotted names so that, for example, if `m_py_obj`
+ // refers to the `sys` module, and `name` == "path.append", then it
+ // will find the function `sys.path.append`.
+
+ size_t dot_pos = name.find_first_of('.');
+ if (dot_pos == llvm::StringRef::npos)
+ {
+ // No dots in the name, we should be able to find the value immediately
+ // as an attribute of `use_object`.
+ return GetAttributeValue(name);
+ }
+
+ // Look up the first piece of the name, and resolve the rest as a child of that.
+ PythonObject parent = ResolveName(name.substr(0, dot_pos));
+ if (!parent.IsAllocated())
+ return PythonObject();
+
+ // Tail recursion.. should be optimized by the compiler
+ return parent.ResolveName(name.substr(dot_pos + 1));
+}
+
bool
PythonObject::HasAttribute(llvm::StringRef attr) const
{
@@ -605,6 +644,62 @@ PythonDictionary::CreateStructuredDictionary() const
return result;
}
+PythonModule::PythonModule() : PythonObject()
+{
+}
+
+PythonModule::PythonModule(PyRefType type, PyObject *py_obj)
+{
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module
+}
+
+PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict)
+{
+}
+
+PythonModule::~PythonModule()
+{
+}
+
+PythonModule
+PythonModule::MainModule()
+{
+ return PythonModule(PyRefType::Borrowed, PyImport_AddModule("__main__"));
+}
+
+bool
+PythonModule::Check(PyObject *py_obj)
+{
+ if (!py_obj)
+ return false;
+
+ return PyModule_Check(py_obj);
+}
+
+void
+PythonModule::Reset(PyRefType type, PyObject *py_obj)
+{
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonModule::Check(py_obj))
+ {
+ PythonObject::Reset();
+ return;
+ }
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+PythonDictionary
+PythonModule::GetDictionary() const
+{
+ return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj));
+}
+
PythonFile::PythonFile()
: PythonObject()
{
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
index 477a427a611..beeea4ca6fa 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
@@ -69,6 +69,7 @@ enum class PyObjectType
Dictionary,
List,
String,
+ Module,
File
};
@@ -185,15 +186,6 @@ public:
return result;
}
- PyObjectType
- GetObjectType() const;
-
- PythonString
- Repr ();
-
- PythonString
- Str ();
-
PythonObject &
operator=(const PythonObject &other)
{
@@ -201,6 +193,21 @@ public:
return *this;
}
+ PyObjectType
+ GetObjectType() const;
+
+ PythonString
+ Repr() const;
+
+ PythonString
+ Str() const;
+
+ static PythonObject
+ ResolveNameGlobal(llvm::StringRef name);
+
+ PythonObject
+ ResolveName(llvm::StringRef name) const;
+
bool
HasAttribute(llvm::StringRef attribute) const;
@@ -224,7 +231,8 @@ public:
return T(PyRefType::Borrowed, m_py_obj);
}
- StructuredData::ObjectSP CreateStructuredObject() const;
+ StructuredData::ObjectSP
+ CreateStructuredObject() const;
protected:
PyObject* m_py_obj;
@@ -338,6 +346,27 @@ public:
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 MainModule();
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+
+ PythonDictionary GetDictionary() const;
+};
+
class PythonFile : public PythonObject
{
public:
OpenPOWER on IntegriCloud