Add PersistentVariableDelegate to handle language-specific dematerialization.

The concept here is that languages may have different ways of communicating
results.  In particular, languages may have different names for their result
variables and in fact may have multiple types of result variables (e.g.,
error results).  Materializer was tied to one specific model of result handling.

Instead, now UserExpressions can register their own handlers for the result
variables they inject.  This allows language-specific code in Materializer to
be moved into the expression parser plug-in, and it simplifies Materializer.
These delegates are subclasses of PersistentVariableDelegate.

PersistentVariableDelegate can provide the name of the result variable, and is
notified when the result variable is populated.  It can also be used to touch
persistent variables if need be, updating language-specific state.  The
UserExpression owns the delegate and can decide on its result based on
consulting all of its (potentially multiple) delegates.

The user expression itself now makes the determination of what the final result
of the expression is, rather than relying on the Materializer, and I've added a
virtual function to UserExpression to allow this.

llvm-svn: 249233
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
index 3f0517f..3da495e 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -56,11 +56,14 @@
 using namespace lldb_private;
 using namespace clang;
 
-ClangExpressionDeclMap::ClangExpressionDeclMap (bool keep_result_in_memory, ExecutionContext &exe_ctx) :
+ClangExpressionDeclMap::ClangExpressionDeclMap (bool keep_result_in_memory,
+                                                Materializer::PersistentVariableDelegate *result_delegate,
+                                                ExecutionContext &exe_ctx) :
     ClangASTSource (exe_ctx.GetTargetSP()),
     m_found_entities (),
     m_struct_members (),
     m_keep_result_in_memory (keep_result_in_memory),
+    m_result_delegate (result_delegate),
     m_parser_vars (),
     m_struct_vars ()
 {
@@ -216,8 +219,12 @@
                                                           ast->getASTContext(),
                                                           parser_type.GetOpaqueQualType()),
                                context);
-
-        uint32_t offset = m_parser_vars->m_materializer->AddResultVariable(user_type, is_lvalue, m_keep_result_in_memory, err);
+        
+        uint32_t offset = m_parser_vars->m_materializer->AddResultVariable(user_type,
+                                                                           is_lvalue,
+                                                                           m_keep_result_in_memory,
+                                                                           m_result_delegate,
+                                                                           err);
 
         ClangExpressionVariable *var = new ClangExpressionVariable(exe_ctx.GetBestExecutionContextScope(),
                                                                    name,
@@ -381,7 +388,7 @@
         if (is_persistent_variable)
         {
             ExpressionVariableSP var_sp(var->shared_from_this());
-            offset = m_parser_vars->m_materializer->AddPersistentVariable(var_sp, err);
+            offset = m_parser_vars->m_materializer->AddPersistentVariable(var_sp, nullptr, err);
         }
         else
         {
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
index 1ed2c4e..a8b874d 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
@@ -71,10 +71,15 @@
     ///     the result persistent variable, and instead marks the variable
     ///     as persisting.
     ///
+    /// @param[in] delegate
+    ///     If non-NULL, use this delegate to report result values.  This
+    ///     allows the client ClangUserExpression to report a result.
+    ///
     /// @param[in] exe_ctx
     ///     The execution context to use when parsing.
     //------------------------------------------------------------------
     ClangExpressionDeclMap (bool keep_result_in_memory,
+                            Materializer::PersistentVariableDelegate *result_delegate,
                             ExecutionContext &exe_ctx);
     
     //------------------------------------------------------------------
@@ -391,6 +396,7 @@
     ExpressionVariableList      m_found_entities;           ///< All entities that were looked up for the parser.
     ExpressionVariableList      m_struct_members;           ///< All entities that need to be placed in the struct.
     bool                        m_keep_result_in_memory;    ///< True if result persistent variables generated by this expression should stay in memory.
+    Materializer::PersistentVariableDelegate *m_result_delegate;  ///< If non-NULL, used to report expression results to ClangUserExpression.
     
     //----------------------------------------------------------------------
     /// The following values should not live beyond parsing
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
index c32ad57..22b0913 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
@@ -336,6 +336,24 @@
     Error err;
 
     InstallContext(exe_ctx);
+    
+    if (Target *target = exe_ctx.GetTargetPtr())
+    {
+        if (PersistentExpressionState *persistent_state = target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))
+        {
+            m_result_delegate.RegisterPersistentState(persistent_state);
+        }
+        else
+        {
+            error_stream.PutCString ("error: couldn't start parsing (no persistent data)");
+            return false;
+        }
+    }
+    else
+    {
+        error_stream.PutCString ("error: couldn't start parsing (no target)");
+        return false;
+    }
 
     ScanContext(exe_ctx, err);
 
@@ -424,7 +442,7 @@
 
     m_materializer_ap.reset(new Materializer());
 
-    ResetDeclMap(exe_ctx, keep_result_in_memory);
+    ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory);
 
     class OnExit
     {
@@ -598,10 +616,16 @@
     return true;
 }
 
-void
-ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(ExecutionContext &exe_ctx, bool keep_result_in_memory)
+lldb::ExpressionVariableSP
+ClangUserExpression::GetResultAfterDematerialization(ExecutionContextScope *exe_scope)
 {
-    m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
+    return m_result_delegate.GetVariable();
+}
+
+void
+ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(ExecutionContext &exe_ctx, Materializer::PersistentVariableDelegate &delegate, bool keep_result_in_memory)
+{
+    m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, &delegate, exe_ctx));
 }
 
 clang::ASTConsumer *
@@ -613,3 +637,31 @@
     return m_result_synthesizer_up.get();
 }
 
+ClangUserExpression::ResultDelegate::ResultDelegate()
+{
+}
+
+ConstString
+ClangUserExpression::ResultDelegate::GetName()
+{
+    return m_persistent_state->GetNextPersistentVariableName();
+}
+
+void
+ClangUserExpression::ResultDelegate::DidDematerialize(lldb::ExpressionVariableSP &variable)
+{
+    m_variable = variable;
+}
+
+void
+ClangUserExpression::ResultDelegate::RegisterPersistentState(PersistentExpressionState *persistent_state)
+{
+    m_persistent_state = persistent_state;
+}
+
+lldb::ExpressionVariableSP &
+ClangUserExpression::ResultDelegate::GetVariable()
+{
+    return m_variable;
+}
+
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
index a2b8bed..ba5f2ea 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
@@ -81,7 +81,7 @@
         }
         
         void
-        ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory);
+        ResetDeclMap (ExecutionContext & exe_ctx, Materializer::PersistentVariableDelegate &result_delegate, bool keep_result_in_memory);
         
         //------------------------------------------------------------------
         /// Return the object that the parser should allow to access ASTs.
@@ -177,10 +177,13 @@
     }
     
     void
-    ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory)
+    ResetDeclMap (ExecutionContext & exe_ctx, Materializer::PersistentVariableDelegate &result_delegate, bool keep_result_in_memory)
     {
-        m_type_system_helper.ResetDeclMap(exe_ctx, keep_result_in_memory);
+        m_type_system_helper.ResetDeclMap(exe_ctx, result_delegate, keep_result_in_memory);
     }
+
+    lldb::ExpressionVariableSP
+    GetResultAfterDematerialization(ExecutionContextScope *exe_scope) override;
     
 private:
     //------------------------------------------------------------------
@@ -197,6 +200,22 @@
                          Stream &error_stream) override;
     
     ClangUserExpressionHelper   m_type_system_helper;
+    
+    class ResultDelegate : public Materializer::PersistentVariableDelegate
+    {
+    public:
+        ResultDelegate();
+        ConstString GetName() override;
+        void DidDematerialize(lldb::ExpressionVariableSP &variable) override;
+        
+        void RegisterPersistentState(PersistentExpressionState *persistent_state);
+        lldb::ExpressionVariableSP &GetVariable();
+    private:
+        PersistentExpressionState *m_persistent_state;
+        lldb::ExpressionVariableSP m_variable;
+    };
+    
+    ResultDelegate                                          m_result_delegate;
 };
 
 } // namespace lldb_private
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
index 457056c..fe044c1 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
@@ -185,5 +185,5 @@
 void
 ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap(ExecutionContext &exe_ctx, bool keep_result_in_memory)
 {
-    m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
+    m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, nullptr, exe_ctx));
 }