Python synthetic children:
 - you can now define a Python class as a synthetic children producer for a type
   the class must adhere to this "interface":
        def __init__(self, valobj, dict):
     	def get_child_at_index(self, index):
     	def get_child_index(self, name):
   then using type synth add -l className typeName
   (e.g. type synth add -l fooSynthProvider foo)
   (This is still WIP with lots to be added)
   A small test case is available also as reference

git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@135865 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/API/SBCommandInterpreter.cpp b/source/API/SBCommandInterpreter.cpp
index 97b9314..1124d56 100644
--- a/source/API/SBCommandInterpreter.cpp
+++ b/source/API/SBCommandInterpreter.cpp
@@ -322,6 +322,19 @@
     const lldb::ValueObjectSP& valobj_sp
 );
 
+extern "C" void*
+LLDBSwigPythonCreateSyntheticProvider 
+(
+    const std::string python_class_name,
+    const char *session_dictionary_name,
+    const lldb::ValueObjectSP& valobj_sp
+);
+
+
+extern "C" uint32_t       LLDBSwigPython_CalculateNumChildren    (void *implementor);
+extern "C" void*          LLDBSwigPython_GetChildAtIndex         (void *implementor, uint32_t idx);
+extern "C" int            LLDBSwigPython_GetIndexOfChildWithName (void *implementor, const char* child_name);
+extern "C" lldb::SBValue* LLDBSWIGPython_CastPyObjectToSBValue   (void* data);
 
 extern "C" void init_lldb(void);
 
@@ -334,6 +347,11 @@
         g_initialized = true;
         ScriptInterpreter::InitializeInterpreter (init_lldb, 
                                                   LLDBSwigPythonBreakpointCallbackFunction,
-                                                  LLDBSwigPythonCallTypeScript);
+                                                  LLDBSwigPythonCallTypeScript,
+                                                  LLDBSwigPythonCreateSyntheticProvider,
+                                                  LLDBSwigPython_CalculateNumChildren,
+                                                  LLDBSwigPython_GetChildAtIndex,
+                                                  LLDBSwigPython_GetIndexOfChildWithName,
+                                                  LLDBSWIGPython_CastPyObjectToSBValue);
     }
 }
diff --git a/source/Commands/CommandObjectType.cpp b/source/Commands/CommandObjectType.cpp
index 3a8b16c..0e15dbc 100644
--- a/source/Commands/CommandObjectType.cpp
+++ b/source/Commands/CommandObjectType.cpp
@@ -10,6 +10,9 @@
 #include "CommandObjectType.h"
 
 // C Includes
+
+#include <ctype.h>
+
 // C++ Includes
 
 #include "lldb/Core/ConstString.h"
@@ -418,8 +421,8 @@
 // CommandObjectTypeSummaryAdd
 //-------------------------------------------------------------------------
 
-static const char *g_reader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
-                                           "def function (valobj,dict):";
+static const char *g_summary_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
+                                                       "def function (valobj,dict):";
 
 class TypeScriptAddInputReader : public InputReaderEZ
 {
@@ -441,7 +444,7 @@
         bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
         if (!batch_mode)
         {
-            out_stream->Printf ("%s\n", g_reader_instructions);
+            out_stream->Printf ("%s\n", g_summary_addreader_instructions);
             if (data.reader.GetPrompt())
                 out_stream->Printf ("%s", data.reader.GetPrompt());
             out_stream->Flush();
@@ -1016,7 +1019,7 @@
                 "     value = valobj.GetChildMemberWithName('value');\n"
                 "     return 'My value is ' + value.GetValue();\n"
                 "DONE\n"
-                "(lldb)"
+                "(lldb) <-- type further LLDB commands here\n"
                 );
 }
 
@@ -2404,6 +2407,10 @@
                 case 'c':
                     m_expr_paths.push_back(option_arg);
                     break;
+                case 'l':
+                    m_class_name = std::string(option_arg);
+                    is_class_based = true;
+                    break;
                 case 'p':
                     m_skip_pointers = true;
                     break;
@@ -2425,10 +2432,12 @@
         OptionParsingStarting ()
         {
             m_cascade = true;
-            m_expr_paths.clear();
+            m_class_name = "";
             m_skip_pointers = false;
             m_skip_references = false;
             m_category = NULL;
+            m_expr_paths.clear();
+            is_class_based = false;
         }
         
         const OptionDefinition*
@@ -2446,9 +2455,13 @@
         bool m_cascade;
         bool m_skip_references;
         bool m_skip_pointers;
+        std::string m_class_name;
+        bool m_input_python;
         option_vector m_expr_paths;
         const char* m_category;
         
+        bool is_class_based;
+        
         typedef option_vector::iterator ExpressionPathsIterator;
     };
     
@@ -2460,7 +2473,114 @@
         return &m_options;
     }
     
+    bool
+    Execute_ChildrenList (Args& command, CommandReturnObject &result)
+    {
+        const size_t argc = command.GetArgumentCount();
+        
+        if (argc < 1)
+        {
+            result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        
+        if (m_options.m_expr_paths.size() == 0)
+        {
+            result.AppendErrorWithFormat ("%s needs one or more children.\n", m_cmd_name.c_str());
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        
+        SyntheticChildrenSP entry;
+        
+        SyntheticFilter* impl = new SyntheticFilter(m_options.m_cascade,
+                                                    m_options.m_skip_pointers,
+                                                    m_options.m_skip_references);
+        
+        entry.reset(impl);
+        
+        // go through the expression paths
+        CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end();
+        
+        for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
+            impl->AddExpressionPath(*begin);
+        
+        
+        // now I have a valid provider, let's add it to every type
+        
+        lldb::FormatCategorySP category;
+        Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category);
+        
+        for (size_t i = 0; i < argc; i++) {
+            const char* typeA = command.GetArgumentAtIndex(i);
+            ConstString typeCS(typeA);
+            if (typeCS)
+                category->Filter()->Add(typeCS.GetCString(), entry);
+            else
+            {
+                result.AppendError("empty typenames not allowed");
+                result.SetStatus(eReturnStatusFailed);
+                return false;
+            }
+        }
+        
+        result.SetStatus(eReturnStatusSuccessFinishNoResult);
+        return result.Succeeded();
+    }
+    
+    bool
+    Execute_PythonClass (Args& command, CommandReturnObject &result)
+    {
+        const size_t argc = command.GetArgumentCount();
+        
+        if (argc < 1)
+        {
+            result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        
+        if (m_options.m_class_name.empty() && !m_options.m_input_python)
+        {
+            result.AppendErrorWithFormat ("%s needs either a Python class name or -P to directly input Python code.\n", m_cmd_name.c_str());
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        
+        SyntheticChildrenSP entry;
+        
+        SyntheticScriptProvider* impl = new SyntheticScriptProvider(m_options.m_cascade,
+                                                                    m_options.m_skip_pointers,
+                                                                    m_options.m_skip_references,
+                                                                    m_options.m_class_name);
+        
+        entry.reset(impl);
+        
+        // now I have a valid provider, let's add it to every type
+        
+        lldb::FormatCategorySP category;
+        Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category);
+        
+        for (size_t i = 0; i < argc; i++) {
+            const char* typeA = command.GetArgumentAtIndex(i);
+            ConstString typeCS(typeA);
+            if (typeCS)
+                category->Filter()->Add(typeCS.GetCString(), entry);
+            else
+            {
+                result.AppendError("empty typenames not allowed");
+                result.SetStatus(eReturnStatusFailed);
+                return false;
+            }
+        }
+        
+        result.SetStatus(eReturnStatusSuccessFinishNoResult);
+        return result.Succeeded();
+    }
+    
 public:
+        
     CommandObjectTypeSynthAdd (CommandInterpreter &interpreter) :
     CommandObject (interpreter,
                    "type synth add",
@@ -2486,55 +2606,10 @@
     bool
     Execute (Args& command, CommandReturnObject &result)
     {
-        const size_t argc = command.GetArgumentCount();
-        
-        if (argc < 1)
-        {
-            result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str());
-            result.SetStatus(eReturnStatusFailed);
-            return false;
-        }
-        
-        if (m_options.m_expr_paths.size() == 0)
-        {
-            result.AppendErrorWithFormat ("%s needs one or more children.\n", m_cmd_name.c_str());
-            result.SetStatus(eReturnStatusFailed);
-            return false;
-        }
-        
-        SyntheticFilterSP entry;
-        
-        entry.reset(new SyntheticFilter(m_options.m_cascade,
-                                        m_options.m_skip_pointers,
-                                        m_options.m_skip_references));
-        
-        // go through the expression paths
-        CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end();
-        
-        for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
-            entry->AddExpressionPath(*begin);
-        
-        
-        // now I have a valid provider, let's add it to every type
-        
-        lldb::FormatCategorySP category;
-        Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category);
-        
-        for (size_t i = 0; i < argc; i++) {
-            const char* typeA = command.GetArgumentAtIndex(i);
-            ConstString typeCS(typeA);
-            if (typeCS)
-                category->Filter()->Add(typeCS.GetCString(), entry);
-            else
-            {
-                result.AppendError("empty typenames not allowed");
-                result.SetStatus(eReturnStatusFailed);
-                return false;
-            }
-        }
-        
-        result.SetStatus(eReturnStatusSuccessFinishNoResult);
-        return result.Succeeded();
+        if (m_options.is_class_based)
+            return Execute_PythonClass(command, result);
+        else
+            return Execute_ChildrenList(command, result);
     }
 };
 
@@ -2542,10 +2617,11 @@
 CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] =
 {
     { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean,    "If true, cascade to derived typedefs."},
-    { LLDB_OPT_SET_ALL, false, "child", 'c', required_argument, NULL, 0, eArgTypeName,    "Include this expression path in the synthetic view."},
     { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeBoolean,         "Don't use this format for pointers-to-type objects."},
     { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeBoolean,         "Don't use this format for references-to-type objects."},
     { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName,         "Add this to the given category instead of the default one."},
+    { LLDB_OPT_SET_1, false, "child", 'c', required_argument, NULL, 0, eArgTypeName,    "Include this expression path in the synthetic view."},
+    { LLDB_OPT_SET_2, false, "python-class", 'l', required_argument, NULL, 0, eArgTypeName,    "Use this Python class to produce synthetic children."},
     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
 };
 
diff --git a/source/Core/Debugger.cpp b/source/Core/Debugger.cpp
index d7538f6..dff2eb0 100644
--- a/source/Core/Debugger.cpp
+++ b/source/Core/Debugger.cpp
@@ -1746,6 +1746,12 @@
     return g_format_manager;
 }
 
+void
+Debugger::Formatting::ForceUpdate()
+{
+    GetFormatManager().Changed();
+}
+
 bool
 Debugger::Formatting::ValueFormats::Get(ValueObject& vobj, ValueFormat::SharedPointer &entry)
 {
@@ -1796,7 +1802,7 @@
 }
 bool
 Debugger::Formatting::GetSyntheticFilter(ValueObject& vobj,
-                                         lldb::SyntheticFilterSP& entry)
+                                         lldb::SyntheticChildrenSP& entry)
 {
     return GetFormatManager().Get(vobj, entry);
 }
diff --git a/source/Core/FormatClasses.cpp b/source/Core/FormatClasses.cpp
index f301a7b..9a232ae 100644
--- a/source/Core/FormatClasses.cpp
+++ b/source/Core/FormatClasses.cpp
@@ -21,8 +21,10 @@
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/FormatClasses.h"
 #include "lldb/Core/StreamString.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Symbol/ClangASTType.h"
 #include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -156,3 +158,25 @@
     sstr.Printf("}");
     return sstr.GetString();
 }
+
+SyntheticScriptProvider::FrontEnd::FrontEnd(std::string pclass,
+                                            lldb::ValueObjectSP be) :
+SyntheticChildrenFrontEnd(be),
+m_python_class(pclass)
+{
+    m_interpreter = be->GetUpdatePoint().GetTarget()->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+    m_wrapper = (PyObject*)m_interpreter->CreateSyntheticScriptedProvider(m_python_class, m_backend);
+}
+
+std::string
+SyntheticScriptProvider::GetDescription()
+{
+    StreamString sstr;
+    sstr.Printf("%s%s%s Python class: %s",
+                m_cascades ? "" : " (not cascading)",
+                m_skip_pointers ? " (skip pointers)" : "",
+                m_skip_references ? " (skip references)" : "",
+                m_python_class.c_str());
+    
+    return sstr.GetString();
+}
\ No newline at end of file
diff --git a/source/Core/ValueObject.cpp b/source/Core/ValueObject.cpp
index 76deaf9..a98d0be 100644
--- a/source/Core/ValueObject.cpp
+++ b/source/Core/ValueObject.cpp
@@ -219,6 +219,8 @@
             m_last_value_format.reset(/*(ValueFormat*)NULL*/);
         if (m_last_synthetic_filter.get())
             m_last_synthetic_filter.reset(/*(SyntheticFilter*)NULL*/);
+
+        m_synthetic_value = NULL;
         
         Debugger::Formatting::ValueFormats::Get(*this, m_last_value_format);
         Debugger::Formatting::GetSummaryFormat(*this, m_last_summary_format);
@@ -1493,7 +1495,8 @@
     if (m_last_synthetic_filter.get() == NULL)
         return;
     
-    m_synthetic_value = new ValueObjectSyntheticFilter(*this, m_last_synthetic_filter);
+    if (m_synthetic_value == NULL)
+        m_synthetic_value = new ValueObjectSynthetic(*this, m_last_synthetic_filter);
     
 }
 
diff --git a/source/Core/ValueObjectSyntheticFilter.cpp b/source/Core/ValueObjectSyntheticFilter.cpp
index 4756b1c..d7d00b6 100644
--- a/source/Core/ValueObjectSyntheticFilter.cpp
+++ b/source/Core/ValueObjectSyntheticFilter.cpp
@@ -35,23 +35,25 @@
 
 using namespace lldb_private;
 
-ValueObjectSyntheticFilter::ValueObjectSyntheticFilter (ValueObject &parent, lldb::SyntheticFilterSP filter) :
+ValueObjectSynthetic::ValueObjectSynthetic (ValueObject &parent, lldb::SyntheticChildrenSP filter) :
     ValueObject(parent),
     m_address (),
     m_type_sp(),
-m_use_synthetic (lldb::eUseSyntheticFilter),
-    m_synth_filter(filter)
+    m_use_synthetic (lldb::eUseSyntheticFilter),
+    m_synth_filter(filter->GetFrontEnd(parent.GetSP())),
+    m_children_byindex(),
+    m_name_toindex()
 {
     SetName (parent.GetName().AsCString());
 }
 
-ValueObjectSyntheticFilter::~ValueObjectSyntheticFilter()
+ValueObjectSynthetic::~ValueObjectSynthetic()
 {
     m_owning_valobj_sp.reset();
 }
 
 lldb::clang_type_t
-ValueObjectSyntheticFilter::GetClangType ()
+ValueObjectSynthetic::GetClangType ()
 {
     if (m_type_sp)
         return m_value.GetClangType();
@@ -60,7 +62,7 @@
 }
 
 ConstString
-ValueObjectSyntheticFilter::GetTypeName()
+ValueObjectSynthetic::GetTypeName()
 {
     const bool success = UpdateValueIfNeeded();
     if (success && m_type_sp)
@@ -70,22 +72,13 @@
 }
 
 uint32_t
-ValueObjectSyntheticFilter::CalculateNumChildren()
+ValueObjectSynthetic::CalculateNumChildren()
 {
-    const bool success = UpdateValueIfNeeded();
-    if (!success)
-        return 0;
-    if (m_synth_filter.get())
-        return m_synth_filter->GetCount();
-    return 0;
-    if (success && m_type_sp)
-        return ClangASTContext::GetNumChildren (GetClangAST (), GetClangType(), true);
-    else
-        return m_parent->GetNumChildren();
+    return m_synth_filter->CalculateNumChildren();
 }
 
 clang::ASTContext *
-ValueObjectSyntheticFilter::GetClangAST ()
+ValueObjectSynthetic::GetClangAST ()
 {
     const bool success = UpdateValueIfNeeded(false);
     if (success && m_type_sp)
@@ -95,7 +88,7 @@
 }
 
 size_t
-ValueObjectSyntheticFilter::GetByteSize()
+ValueObjectSynthetic::GetByteSize()
 {
     const bool success = UpdateValueIfNeeded();
     if (success && m_type_sp)
@@ -105,13 +98,13 @@
 }
 
 lldb::ValueType
-ValueObjectSyntheticFilter::GetValueType() const
+ValueObjectSynthetic::GetValueType() const
 {
     return m_parent->GetValueType();
 }
 
 bool
-ValueObjectSyntheticFilter::UpdateValue ()
+ValueObjectSynthetic::UpdateValue ()
 {
     SetValueIsValid (false);
     m_error.Clear();
@@ -124,46 +117,61 @@
         return false;
     }
 
+    m_children_byindex.clear();
+    m_name_toindex.clear();
+    
     SetValueIsValid(true);
     return true;
 }
 
 lldb::ValueObjectSP
-ValueObjectSyntheticFilter::GetChildAtIndex (uint32_t idx, bool can_create)
+ValueObjectSynthetic::GetChildAtIndex (uint32_t idx, bool can_create)
 {
-    if (!m_synth_filter.get())
-        return lldb::ValueObjectSP();
-    if (idx >= m_synth_filter->GetCount())
-        return lldb::ValueObjectSP();
-    return m_parent->GetSyntheticExpressionPathChild(m_synth_filter->GetExpressionPathAtIndex(idx).c_str(), can_create);
+    ByIndexIterator iter = m_children_byindex.find(idx);
+    
+    if (iter == m_children_byindex.end())
+    {
+        if (can_create)
+        {
+            lldb::ValueObjectSP synth_guy = m_synth_filter->GetChildAtIndex (idx, can_create);
+            m_children_byindex[idx]= synth_guy;
+            return synth_guy;
+        }
+        else
+            return lldb::ValueObjectSP();
+    }
+    else
+        return iter->second;
 }
 
 lldb::ValueObjectSP
-ValueObjectSyntheticFilter::GetChildMemberWithName (const ConstString &name, bool can_create)
+ValueObjectSynthetic::GetChildMemberWithName (const ConstString &name, bool can_create)
 {
-    if (!m_synth_filter.get())
+    
+    uint32_t index = GetIndexOfChildWithName(name);
+    
+    if (index == UINT32_MAX)
         return lldb::ValueObjectSP();
-    uint32_t idx = GetIndexOfChildWithName(name);
-    if (idx >= m_synth_filter->GetCount())
-        return lldb::ValueObjectSP();
-    return m_parent->GetSyntheticExpressionPathChild(name.GetCString(), can_create);
+    
+    return GetChildAtIndex(index, can_create);
 }
 
 uint32_t
-ValueObjectSyntheticFilter::GetIndexOfChildWithName (const ConstString &name)
+ValueObjectSynthetic::GetIndexOfChildWithName (const ConstString &name)
 {
-    const char* name_cstr = name.GetCString();
-    for (int i = 0; i < m_synth_filter->GetCount(); i++)
+    NameToIndexIterator iter = m_name_toindex.find(name.GetCString());
+    
+    if (iter == m_name_toindex.end())
     {
-        const char* expr_cstr = m_synth_filter->GetExpressionPathAtIndex(i).c_str();
-        if (::strcmp(name_cstr, expr_cstr))
-            return i;
+        uint32_t index = m_synth_filter->GetIndexOfChildWithName (name);
+        m_name_toindex[name.GetCString()] = index;
+        return index;
     }
-    return UINT32_MAX;
+    return iter->second;
 }
 
 bool
-ValueObjectSyntheticFilter::IsInScope ()
+ValueObjectSynthetic::IsInScope ()
 {
     return m_parent->IsInScope();
 }
diff --git a/source/Interpreter/CommandObjectScript.cpp b/source/Interpreter/CommandObjectScript.cpp
index 70a4ead..e586497 100644
--- a/source/Interpreter/CommandObjectScript.cpp
+++ b/source/Interpreter/CommandObjectScript.cpp
@@ -13,6 +13,9 @@
 // C++ Includes
 // Other libraries and framework includes
 // Project includes
+
+#include "lldb/Core/Debugger.h"
+
 #include "lldb/Interpreter/Args.h"
 
 #include "lldb/Interpreter/CommandReturnObject.h"
@@ -54,6 +57,8 @@
         result.SetStatus (eReturnStatusFailed);
     }
 
+    Debugger::Formatting::ForceUpdate(); // script might change Python code we use for formatting.. make sure we keep up to date with it
+    
     if (command == NULL || command[0] == '\0') {
         script_interpreter->ExecuteInterpreterLoop ();
         result.SetStatus (eReturnStatusSuccessFinishNoResult);
diff --git a/source/Interpreter/ScriptInterpreter.cpp b/source/Interpreter/ScriptInterpreter.cpp
index 294aeec..27c7bad 100644
--- a/source/Interpreter/ScriptInterpreter.cpp
+++ b/source/Interpreter/ScriptInterpreter.cpp
@@ -93,11 +93,21 @@
 void
 ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_callback,
                                           SWIGBreakpointCallbackFunction python_swig_breakpoint_callback,
-                                          SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback)
+                                          SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback,
+                                          SWIGPythonCreateSyntheticProvider python_swig_synthetic_script,
+                                          SWIGPythonCalculateNumChildren python_swig_calc_children,
+                                          SWIGPythonGetChildAtIndex python_swig_get_child_index,
+                                          SWIGPythonGetIndexOfChildWithName python_swig_get_index_child,
+                                          SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalue)
 {
     ScriptInterpreterPython::InitializeInterpreter (python_swig_init_callback, 
                                                     python_swig_breakpoint_callback,
-                                                    python_swig_typescript_callback);
+                                                    python_swig_typescript_callback,
+                                                    python_swig_synthetic_script,
+                                                    python_swig_calc_children,
+                                                    python_swig_get_child_index,
+                                                    python_swig_get_index_child,
+                                                    python_swig_cast_to_sbvalue);
 }
 
 void
diff --git a/source/Interpreter/ScriptInterpreterPython.cpp b/source/Interpreter/ScriptInterpreterPython.cpp
index 57a5929..03eadc6 100644
--- a/source/Interpreter/ScriptInterpreterPython.cpp
+++ b/source/Interpreter/ScriptInterpreterPython.cpp
@@ -35,7 +35,11 @@
 static ScriptInterpreter::SWIGInitCallback g_swig_init_callback = NULL;
 static ScriptInterpreter::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = NULL;
 static ScriptInterpreter::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = NULL;
-
+static ScriptInterpreter::SWIGPythonCreateSyntheticProvider g_swig_synthetic_script = NULL;
+static ScriptInterpreter::SWIGPythonCalculateNumChildren g_swig_calc_children = NULL;
+static ScriptInterpreter::SWIGPythonGetChildAtIndex g_swig_get_child_index = NULL;
+static ScriptInterpreter::SWIGPythonGetIndexOfChildWithName g_swig_get_index_child = NULL;
+static ScriptInterpreter::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue  = NULL;
 
 static int
 _check_and_flush (FILE *stream)
@@ -1245,6 +1249,55 @@
     return true;
 }
 
+void*
+ScriptInterpreterPython::CreateSyntheticScriptedProvider (std::string class_name,
+                                                          lldb::ValueObjectSP valobj)
+{
+    if (class_name.empty())
+        return NULL;
+    
+    if (!valobj.get())
+        return NULL;
+    
+    Target *target = valobj->GetUpdatePoint().GetTarget();
+    
+    if (!target)
+        return NULL;
+    
+    Debugger &debugger = target->GetDebugger();
+    ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
+    ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter;
+    
+    if (!script_interpreter)
+        return NULL;
+    
+    void* ret_val;
+    
+    FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout);
+    if (CurrentThreadHasPythonLock())
+    {
+        python_interpreter->EnterSession ();
+        ret_val = g_swig_synthetic_script    (class_name, 
+                                              python_interpreter->m_dictionary_name.c_str(),
+                                              valobj);
+        python_interpreter->LeaveSession ();
+    }
+    else
+    {
+        while (!GetPythonLock (1))
+            fprintf (tmp_fh, 
+                     "Python interpreter locked on another thread; waiting to acquire lock...\n");
+        python_interpreter->EnterSession ();
+        ret_val = g_swig_synthetic_script (class_name, 
+                                           python_interpreter->m_dictionary_name.c_str(), 
+                                           valobj);
+        python_interpreter->LeaveSession ();
+        ReleasePythonLock ();
+    }
+    
+    return ret_val;
+}
+
 bool
 ScriptInterpreterPython::GenerateTypeScriptFunction (const char* oneliner, StringList &output)
 {
@@ -1565,15 +1618,161 @@
     return NULL;
 }
 
+uint32_t
+ScriptInterpreterPython::CalculateNumChildren (void *implementor)
+{
+    if (!implementor)
+        return 0;
+    
+    if (!g_swig_calc_children)
+        return 0;
+    
+    ScriptInterpreterPython *python_interpreter = this;
+    
+    uint32_t ret_val = 0;
+    
+    FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout);
+    if (CurrentThreadHasPythonLock())
+    {
+        python_interpreter->EnterSession ();
+        ret_val = g_swig_calc_children       (implementor);
+        python_interpreter->LeaveSession ();
+    }
+    else
+    {
+        while (!GetPythonLock (1))
+            fprintf (tmp_fh, 
+                     "Python interpreter locked on another thread; waiting to acquire lock...\n");
+        python_interpreter->EnterSession ();
+        ret_val = g_swig_calc_children       (implementor);
+        python_interpreter->LeaveSession ();
+        ReleasePythonLock ();
+    }
+    
+    return ret_val;
+}
+
+void*
+ScriptInterpreterPython::GetChildAtIndex (void *implementor, uint32_t idx)
+{
+    if (!implementor)
+        return 0;
+    
+    if (!g_swig_get_child_index)
+        return 0;
+    
+    ScriptInterpreterPython *python_interpreter = this;
+    
+    void* ret_val = NULL;
+    
+    FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout);
+    if (CurrentThreadHasPythonLock())
+    {
+        python_interpreter->EnterSession ();
+        ret_val = g_swig_get_child_index       (implementor,idx);
+        python_interpreter->LeaveSession ();
+    }
+    else
+    {
+        while (!GetPythonLock (1))
+            fprintf (tmp_fh, 
+                     "Python interpreter locked on another thread; waiting to acquire lock...\n");
+        python_interpreter->EnterSession ();
+        ret_val = g_swig_get_child_index       (implementor,idx);
+        python_interpreter->LeaveSession ();
+        ReleasePythonLock ();
+    }
+    
+    return ret_val;
+}
+
+int
+ScriptInterpreterPython::GetIndexOfChildWithName (void *implementor, const char* child_name)
+{
+    if (!implementor)
+        return UINT32_MAX;
+    
+    if (!g_swig_get_index_child)
+        return UINT32_MAX;
+    
+    ScriptInterpreterPython *python_interpreter = this;
+    
+    int ret_val = UINT32_MAX;
+    
+    FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout);
+    if (CurrentThreadHasPythonLock())
+    {
+        python_interpreter->EnterSession ();
+        ret_val = g_swig_get_index_child       (implementor, child_name);
+        python_interpreter->LeaveSession ();
+    }
+    else
+    {
+        while (!GetPythonLock (1))
+            fprintf (tmp_fh, 
+                     "Python interpreter locked on another thread; waiting to acquire lock...\n");
+        python_interpreter->EnterSession ();
+        ret_val = g_swig_get_index_child       (implementor, child_name);
+        python_interpreter->LeaveSession ();
+        ReleasePythonLock ();
+    }
+    
+    return ret_val;
+}
+
+lldb::SBValue*
+ScriptInterpreterPython::CastPyObjectToSBValue (void* data)
+{
+    if (!data)
+        return NULL;
+    
+    if (!g_swig_cast_to_sbvalue)
+        return NULL;
+    
+    ScriptInterpreterPython *python_interpreter = this;
+    
+    lldb::SBValue* ret_val = NULL;
+    
+    FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout);
+    if (CurrentThreadHasPythonLock())
+    {
+        python_interpreter->EnterSession ();
+        ret_val = g_swig_cast_to_sbvalue       (data);
+        python_interpreter->LeaveSession ();
+    }
+    else
+    {
+        while (!GetPythonLock (1))
+            fprintf (tmp_fh, 
+                     "Python interpreter locked on another thread; waiting to acquire lock...\n");
+        python_interpreter->EnterSession ();
+        ret_val = g_swig_cast_to_sbvalue       (data);
+        python_interpreter->LeaveSession ();
+        ReleasePythonLock ();
+    }
+    
+    return ret_val;
+}
+
 
 void
 ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback python_swig_init_callback,
                                                 SWIGBreakpointCallbackFunction python_swig_breakpoint_callback,
-                                                SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback)
+                                                SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback,
+                                                SWIGPythonCreateSyntheticProvider python_swig_synthetic_script,
+                                                SWIGPythonCalculateNumChildren python_swig_calc_children,
+                                                SWIGPythonGetChildAtIndex python_swig_get_child_index,
+                                                SWIGPythonGetIndexOfChildWithName python_swig_get_index_child,
+                                                SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalue)
 {
     g_swig_init_callback = python_swig_init_callback;
     g_swig_breakpoint_callback = python_swig_breakpoint_callback;
     g_swig_typescript_callback = python_swig_typescript_callback;
+    g_swig_synthetic_script = python_swig_synthetic_script;
+    g_swig_calc_children = python_swig_calc_children;
+    g_swig_get_child_index = python_swig_get_child_index;
+    g_swig_get_index_child = python_swig_get_index_child;
+    g_swig_cast_to_sbvalue = python_swig_cast_to_sbvalue;
 }
 
 void