[Lldb-commits] [lldb] r251820 - Create an expression parser for Go.

Ryan Brown via lldb-commits lldb-commits at lists.llvm.org
Mon Nov 2 11:30:42 PST 2015


Author: ribrdb
Date: Mon Nov  2 13:30:40 2015
New Revision: 251820

URL: http://llvm.org/viewvc/llvm-project?rev=251820&view=rev
Log:
Create an expression parser for Go.

The Go interpreter doesn't JIT or use LLVM, so this also
moves all the JIT related code from UserExpression to a new class LLVMUserExpression.

Differential Revision: http://reviews.llvm.org/D13073

Fix merge

Added:
    lldb/trunk/include/lldb/Expression/LLVMUserExpression.h
    lldb/trunk/source/Expression/LLVMUserExpression.cpp
    lldb/trunk/source/Plugins/ExpressionParser/Go/
    lldb/trunk/source/Plugins/ExpressionParser/Go/CMakeLists.txt
    lldb/trunk/source/Plugins/ExpressionParser/Go/GoAST.h
    lldb/trunk/source/Plugins/ExpressionParser/Go/GoLexer.cpp
    lldb/trunk/source/Plugins/ExpressionParser/Go/GoLexer.h
    lldb/trunk/source/Plugins/ExpressionParser/Go/GoParser.cpp
    lldb/trunk/source/Plugins/ExpressionParser/Go/GoParser.h
    lldb/trunk/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp
    lldb/trunk/source/Plugins/ExpressionParser/Go/GoUserExpression.h
    lldb/trunk/source/Plugins/ExpressionParser/Go/Makefile
    lldb/trunk/source/Plugins/ExpressionParser/Go/gen_go_ast.py
    lldb/trunk/test/lang/go/expressions/
    lldb/trunk/test/lang/go/expressions/TestExpressions.py
    lldb/trunk/test/lang/go/expressions/main.go
    lldb/trunk/unittests/Expression/
    lldb/trunk/unittests/Expression/CMakeLists.txt
    lldb/trunk/unittests/Expression/GoParserTest.cpp
Modified:
    lldb/trunk/.clang-format
    lldb/trunk/cmake/LLDBDependencies.cmake
    lldb/trunk/include/lldb/Expression/UserExpression.h
    lldb/trunk/include/lldb/Symbol/GoASTContext.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/API/SBFrame.cpp
    lldb/trunk/source/Expression/CMakeLists.txt
    lldb/trunk/source/Expression/UserExpression.cpp
    lldb/trunk/source/Plugins/ExpressionParser/CMakeLists.txt
    lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
    lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
    lldb/trunk/source/Symbol/GoASTContext.cpp
    lldb/trunk/unittests/CMakeLists.txt

Modified: lldb/trunk/.clang-format
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/.clang-format?rev=251820&r1=251819&r2=251820&view=diff
==============================================================================
--- lldb/trunk/.clang-format (original)
+++ lldb/trunk/.clang-format Mon Nov  2 13:30:40 2015
@@ -4,5 +4,5 @@ ColumnLimit:     120
 BreakBeforeBraces: Allman
 AlwaysBreakAfterDefinitionReturnType: true
 AllowShortFunctionsOnASingleLine: Inline
-BreakConstructorInitializersBeforeComma: true
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
 IndentCaseLabels: true

Modified: lldb/trunk/cmake/LLDBDependencies.cmake
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/cmake/LLDBDependencies.cmake?rev=251820&r1=251819&r2=251820&view=diff
==============================================================================
--- lldb/trunk/cmake/LLDBDependencies.cmake (original)
+++ lldb/trunk/cmake/LLDBDependencies.cmake Mon Nov  2 13:30:40 2015
@@ -74,6 +74,7 @@ set( LLDB_USED_LIBS
   lldbPluginProcessElfCore
   lldbPluginJITLoaderGDB
   lldbPluginExpressionParserClang
+  lldbPluginExpressionParserGo
   )
 
 # Windows-only libraries

Added: lldb/trunk/include/lldb/Expression/LLVMUserExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/LLVMUserExpression.h?rev=251820&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Expression/LLVMUserExpression.h (added)
+++ lldb/trunk/include/lldb/Expression/LLVMUserExpression.h Mon Nov  2 13:30:40 2015
@@ -0,0 +1,108 @@
+//===-- LLVMUserExpression.h ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_LLVMUserExpression_h
+#define liblldb_LLVMUserExpression_h
+
+// C Includes
+// C++ Includes
+#include <string>
+#include <map>
+#include <vector>
+
+// Project includes
+#include "lldb/Expression/UserExpression.h"
+
+namespace lldb_private
+{
+
+//----------------------------------------------------------------------
+/// @class LLVMUserExpression LLVMUserExpression.h "lldb/Expression/LLVMUserExpression.h"
+/// @brief Encapsulates a one-time expression for use in lldb.
+///
+/// LLDB uses expressions for various purposes, notably to call functions
+/// and as a backend for the expr command.  LLVMUserExpression is a virtual base
+/// class that encapsulates the objects needed to parse and JIT an expression.
+/// The actual parsing part will be provided by the specific implementations
+/// of LLVMUserExpression - which will be vended through the appropriate TypeSystem.
+//----------------------------------------------------------------------
+class LLVMUserExpression : public UserExpression
+{
+  public:
+    LLVMUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix,
+                       lldb::LanguageType language, ResultType desired_type);
+    ~LLVMUserExpression() override;
+
+    lldb::ExpressionResults Execute(Stream &error_stream, ExecutionContext &exe_ctx,
+                                    const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me,
+                                    lldb::ExpressionVariableSP &result) override;
+
+    bool FinalizeJITExecution(Stream &error_stream, ExecutionContext &exe_ctx, lldb::ExpressionVariableSP &result,
+                              lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS,
+                              lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS) override;
+
+    bool
+    CanInterpret() override
+    {
+        return m_can_interpret;
+    }
+
+    //------------------------------------------------------------------
+    /// Return the string that the parser should parse.  Must be a full
+    /// translation unit.
+    //------------------------------------------------------------------
+    const char *
+    Text() override
+    {
+        return m_transformed_text.c_str();
+    }
+
+    lldb::ModuleSP GetJITModule() override;
+
+  protected:
+    virtual void ScanContext(ExecutionContext &exe_ctx, lldb_private::Error &err) = 0;
+
+    bool PrepareToExecuteJITExpression(Stream &error_stream, ExecutionContext &exe_ctx, lldb::addr_t &struct_address);
+    virtual bool
+    AddInitialArguments(ExecutionContext &exe_ctx, std::vector<lldb::addr_t> &args, Stream &error_stream)
+    {
+        return true;
+    }
+
+    lldb::addr_t m_stack_frame_bottom; ///< The bottom of the allocated stack frame.
+    lldb::addr_t m_stack_frame_top;    ///< The top of the allocated stack frame.
+
+    bool m_allow_cxx;               ///< True if the language allows C++.
+    bool m_allow_objc;              ///< True if the language allows Objective-C.
+    std::string m_transformed_text; ///< The text of the expression, as send to the parser
+
+    std::shared_ptr<IRExecutionUnit> m_execution_unit_sp; ///< The execution unit the expression is stored in.
+    std::unique_ptr<Materializer> m_materializer_ap;      ///< The materializer to use when running the expression.
+    lldb::ModuleWP m_jit_module_wp;
+    bool m_enforce_valid_object; ///< True if the expression parser should enforce the presence of a valid class pointer
+                                 ///in order to generate the expression as a method.
+    bool m_in_cplusplus_method;  ///< True if the expression is compiled as a C++ member function (true if it was parsed
+                                 ///when exe_ctx was in a C++ method).
+    bool m_in_objectivec_method; ///< True if the expression is compiled as an Objective-C method (true if it was parsed
+                                 ///when exe_ctx was in an Objective-C method).
+    bool m_in_static_method; ///< True if the expression is compiled as a static (or class) method (currently true if it
+                             ///was parsed when exe_ctx was in an Objective-C class method).
+    bool m_needs_object_ptr; ///< True if "this" or "self" must be looked up and passed in.  False if the expression
+                             ///doesn't really use them and they can be NULL.
+    bool m_const_object;     ///< True if "this" is const.
+    Target *m_target;        ///< The target for storing persistent data like types and variables.
+
+    bool m_can_interpret; ///< True if the expression could be evaluated statically; false otherwise.
+    lldb::addr_t
+        m_materialized_address; ///< The address at which the arguments to the expression have been materialized.
+    Materializer::DematerializerSP m_dematerializer_sp; ///< The dematerializer.
+};
+
+} // namespace lldb_private
+#endif

Modified: lldb/trunk/include/lldb/Expression/UserExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/UserExpression.h?rev=251820&r1=251819&r2=251820&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/UserExpression.h (original)
+++ lldb/trunk/include/lldb/Expression/UserExpression.h Mon Nov  2 13:30:40 2015
@@ -102,11 +102,7 @@ public:
            bool keep_result_in_memory,
            bool generate_debug_info) = 0;
 
-    bool
-    CanInterpret ()
-    {
-        return m_can_interpret;
-    }
+    virtual bool CanInterpret() = 0;
 
     bool
     MatchesContext (ExecutionContext &exe_ctx);
@@ -138,12 +134,10 @@ public:
     /// @return
     ///     A Process::Execution results value.
     //------------------------------------------------------------------
-    lldb::ExpressionResults
-    Execute (Stream &error_stream,
-             ExecutionContext &exe_ctx,
-             const EvaluateExpressionOptions& options,
-             lldb::UserExpressionSP &shared_ptr_to_me,
-             lldb::ExpressionVariableSP &result);
+    virtual lldb::ExpressionResults Execute(Stream &error_stream, ExecutionContext &exe_ctx,
+                                            const EvaluateExpressionOptions &options,
+                                            lldb::UserExpressionSP &shared_ptr_to_me,
+                                            lldb::ExpressionVariableSP &result) = 0;
 
     //------------------------------------------------------------------
     /// Apply the side effects of the function to program state.
@@ -168,21 +162,18 @@ public:
     /// @return
     ///     A Process::Execution results value.
     //------------------------------------------------------------------
-    bool
-    FinalizeJITExecution (Stream &error_stream,
-                          ExecutionContext &exe_ctx,
-                          lldb::ExpressionVariableSP &result,
-                          lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS,
-                          lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS);
+    virtual bool FinalizeJITExecution(Stream &error_stream, ExecutionContext &exe_ctx,
+                                      lldb::ExpressionVariableSP &result,
+                                      lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS,
+                                      lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS) = 0;
 
     //------------------------------------------------------------------
-    /// Return the string that the parser should parse.  Must be a full
-    /// translation unit.
+    /// Return the string that the parser should parse.
     //------------------------------------------------------------------
     const char *
     Text() override
     {
-        return m_transformed_text.c_str();
+        return m_expr_text.c_str();
     }
 
     //------------------------------------------------------------------
@@ -251,6 +242,12 @@ public:
         return lldb::ExpressionVariableSP();
     }
 
+    virtual lldb::ModuleSP
+    GetJITModule()
+    {
+        return lldb::ModuleSP();
+    }
+
     //------------------------------------------------------------------
     /// Evaluate one expression in the scratch context of the
     /// target passed in the exe_ctx and return its result.
@@ -308,23 +305,6 @@ protected:
     /// Populate m_in_cplusplus_method and m_in_objectivec_method based on the environment.
     //------------------------------------------------------------------
 
-    virtual void
-    ScanContext (ExecutionContext &exe_ctx,
-                 lldb_private::Error &err) = 0;
-
-    bool
-    PrepareToExecuteJITExpression (Stream &error_stream,
-                                   ExecutionContext &exe_ctx,
-                                   lldb::addr_t &struct_address);
-    
-    virtual bool
-    AddInitialArguments (ExecutionContext &exe_ctx,
-                         std::vector<lldb::addr_t> &args,
-                         Stream &error_stream)
-    {
-        return true;
-    }
-
     void
     InstallContext (ExecutionContext &exe_ctx);
 
@@ -335,31 +315,11 @@ protected:
                          lldb::StackFrameSP &frame_sp);
 
     Address                                     m_address;              ///< The address the process is stopped in.
-    lldb::addr_t                                m_stack_frame_bottom;   ///< The bottom of the allocated stack frame.
-    lldb::addr_t                                m_stack_frame_top;      ///< The top of the allocated stack frame.
-
     std::string                                 m_expr_text;            ///< The text of the expression, as typed by the user
     std::string                                 m_expr_prefix;          ///< The text of the translation-level definitions, as provided by the user
     lldb::LanguageType                          m_language;             ///< The language to use when parsing (eLanguageTypeUnknown means use defaults)
-    bool                                        m_allow_cxx;            ///< True if the language allows C++.
-    bool                                        m_allow_objc;           ///< True if the language allows Objective-C.
-    std::string                                 m_transformed_text;     ///< The text of the expression, as send to the parser
     ResultType                                  m_desired_type;         ///< The type to coerce the expression's result to.  If eResultTypeAny, inferred from the expression.
 
-    std::shared_ptr<IRExecutionUnit>            m_execution_unit_sp;    ///< The execution unit the expression is stored in.
-    std::unique_ptr<Materializer>               m_materializer_ap;      ///< The materializer to use when running the expression.
-    lldb::ModuleWP                              m_jit_module_wp;
-    bool                                        m_enforce_valid_object; ///< True if the expression parser should enforce the presence of a valid class pointer in order to generate the expression as a method.
-    bool                                        m_in_cplusplus_method;  ///< True if the expression is compiled as a C++ member function (true if it was parsed when exe_ctx was in a C++ method).
-    bool                                        m_in_objectivec_method; ///< True if the expression is compiled as an Objective-C method (true if it was parsed when exe_ctx was in an Objective-C method).
-    bool                                        m_in_static_method;     ///< True if the expression is compiled as a static (or class) method (currently true if it was parsed when exe_ctx was in an Objective-C class method).
-    bool                                        m_needs_object_ptr;     ///< True if "this" or "self" must be looked up and passed in.  False if the expression doesn't really use them and they can be nullptr.
-    bool                                        m_const_object;         ///< True if "this" is const.
-    Target                                     *m_target;               ///< The target for storing persistent data like types and variables.
-
-    bool                                        m_can_interpret;        ///< True if the expression could be evaluated statically; false otherwise.
-    lldb::addr_t                                m_materialized_address; ///< The address at which the arguments to the expression have been materialized.
-    Materializer::DematerializerSP              m_dematerializer_sp;    ///< The dematerializer.
 };
 
 } // namespace lldb_private

Modified: lldb/trunk/include/lldb/Symbol/GoASTContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/GoASTContext.h?rev=251820&r1=251819&r2=251820&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/GoASTContext.h (original)
+++ lldb/trunk/include/lldb/Symbol/GoASTContext.h Mon Nov  2 13:30:40 2015
@@ -254,8 +254,7 @@ class GoASTContext : public TypeSystem
 
     lldb::BasicType GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) override;
 
-    CompilerType GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
-                                                     size_t bit_size) override;
+    CompilerType GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size) override;
 
     uint32_t GetNumFields(lldb::opaque_compiler_type_t type) override;
 
@@ -394,6 +393,15 @@ class GoASTContext : public TypeSystem
     const GoASTContext &operator=(const GoASTContext &) = delete;
 };
 
-} // namespace lldb_private
+class GoASTContextForExpr : public GoASTContext
+{
+  public:
+    GoASTContextForExpr(lldb::TargetSP target) : m_target_wp(target) {}
+    UserExpression *GetUserExpression(const char *expr, const char *expr_prefix, lldb::LanguageType language,
+                                      Expression::ResultType desired_type) override;
 
+  private:
+    lldb::TargetWP m_target_wp;
+};
+}
 #endif // liblldb_GoASTContext_h_

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=251820&r1=251819&r2=251820&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Mon Nov  2 13:30:40 2015
@@ -839,10 +839,14 @@
 		9AC703AF117675410086C050 /* SBInstruction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AC703AE117675410086C050 /* SBInstruction.cpp */; };
 		9AC703B1117675490086C050 /* SBInstructionList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AC703B0117675490086C050 /* SBInstructionList.cpp */; };
 		A36FF33C17D8E94600244D40 /* OptionParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A36FF33B17D8E94600244D40 /* OptionParser.cpp */; };
+		AE44FB301BB07EB20033EB62 /* GoUserExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE44FB2C1BB07DD80033EB62 /* GoUserExpression.cpp */; };
+		AE44FB311BB07EB80033EB62 /* GoLexer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE44FB2A1BB07DD80033EB62 /* GoLexer.cpp */; };
+		AE44FB321BB07EBC0033EB62 /* GoParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE44FB2B1BB07DD80033EB62 /* GoParser.cpp */; };
 		AE44FB3E1BB485960033EB62 /* GoLanguageRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE44FB3D1BB485960033EB62 /* GoLanguageRuntime.cpp */; };
 		AE6897281B94F6DE0018845D /* DWARFASTParserGo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE6897261B94F6DE0018845D /* DWARFASTParserGo.cpp */; };
 		AE7F56291B8FE418001377A8 /* GoASTContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEFFBA7C1AC4835D0087B932 /* GoASTContext.cpp */; };
 		AE8F624919EF3E1E00326B21 /* OperatingSystemGo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE8F624719EF3E1E00326B21 /* OperatingSystemGo.cpp */; };
+		AEB0E4591BD6E9F800B24093 /* LLVMUserExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEB0E4581BD6E9F800B24093 /* LLVMUserExpression.cpp */; };
 		AEEA34051AC88A7400AB639D /* TypeSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEEA34041AC88A7400AB639D /* TypeSystem.cpp */; };
 		AF061F87182C97ED00B6A19C /* RegisterContextHistory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF061F85182C97ED00B6A19C /* RegisterContextHistory.cpp */; };
 		AF0C112818580CD800C4C45B /* QueueItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF0C112718580CD800C4C45B /* QueueItem.cpp */; };
@@ -2683,12 +2687,21 @@
 		9AF16CC7114086A1007A7B3F /* SBBreakpointLocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBBreakpointLocation.cpp; path = source/API/SBBreakpointLocation.cpp; sourceTree = "<group>"; };
 		A36FF33B17D8E94600244D40 /* OptionParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OptionParser.cpp; sourceTree = "<group>"; };
 		A36FF33D17D8E98800244D40 /* OptionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionParser.h; path = include/lldb/Host/OptionParser.h; sourceTree = "<group>"; };
+		AE44FB261BB07DC60033EB62 /* GoAST.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GoAST.h; path = ExpressionParser/Go/GoAST.h; sourceTree = "<group>"; };
+		AE44FB271BB07DC60033EB62 /* GoLexer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GoLexer.h; path = ExpressionParser/Go/GoLexer.h; sourceTree = "<group>"; };
+		AE44FB281BB07DC60033EB62 /* GoParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GoParser.h; path = ExpressionParser/Go/GoParser.h; sourceTree = "<group>"; };
+		AE44FB291BB07DC60033EB62 /* GoUserExpression.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GoUserExpression.h; path = ExpressionParser/Go/GoUserExpression.h; sourceTree = "<group>"; };
+		AE44FB2A1BB07DD80033EB62 /* GoLexer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GoLexer.cpp; path = ExpressionParser/Go/GoLexer.cpp; sourceTree = "<group>"; };
+		AE44FB2B1BB07DD80033EB62 /* GoParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GoParser.cpp; path = ExpressionParser/Go/GoParser.cpp; sourceTree = "<group>"; };
+		AE44FB2C1BB07DD80033EB62 /* GoUserExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GoUserExpression.cpp; path = ExpressionParser/Go/GoUserExpression.cpp; sourceTree = "<group>"; };
 		AE44FB3C1BB4858A0033EB62 /* GoLanguageRuntime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GoLanguageRuntime.h; path = Go/GoLanguageRuntime.h; sourceTree = "<group>"; };
 		AE44FB3D1BB485960033EB62 /* GoLanguageRuntime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GoLanguageRuntime.cpp; path = Go/GoLanguageRuntime.cpp; sourceTree = "<group>"; };
 		AE6897261B94F6DE0018845D /* DWARFASTParserGo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFASTParserGo.cpp; sourceTree = "<group>"; };
 		AE6897271B94F6DE0018845D /* DWARFASTParserGo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFASTParserGo.h; sourceTree = "<group>"; };
 		AE8F624719EF3E1E00326B21 /* OperatingSystemGo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OperatingSystemGo.cpp; path = Go/OperatingSystemGo.cpp; sourceTree = "<group>"; };
 		AE8F624819EF3E1E00326B21 /* OperatingSystemGo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OperatingSystemGo.h; path = Go/OperatingSystemGo.h; sourceTree = "<group>"; };
+		AEB0E4581BD6E9F800B24093 /* LLVMUserExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLVMUserExpression.cpp; path = source/Expression/LLVMUserExpression.cpp; sourceTree = "<group>"; };
+		AEB0E45A1BD6EA1400B24093 /* LLVMUserExpression.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LLVMUserExpression.h; path = include/lldb/Expression/LLVMUserExpression.h; sourceTree = "<group>"; };
 		AEEA33F61AC74FE700AB639D /* TypeSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TypeSystem.h; path = include/lldb/Symbol/TypeSystem.h; sourceTree = "<group>"; };
 		AEEA34041AC88A7400AB639D /* TypeSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeSystem.cpp; path = source/Symbol/TypeSystem.cpp; sourceTree = "<group>"; };
 		AEEA340F1ACA08A000AB639D /* GoASTContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GoASTContext.h; path = include/lldb/Symbol/GoASTContext.h; sourceTree = "<group>"; };
@@ -4528,6 +4541,8 @@
 				4C0083321B9A5DE200D5CF24 /* FunctionCaller.cpp */,
 				4C00832E1B9A58A700D5CF24 /* UserExpression.h */,
 				4C0083331B9A5DE200D5CF24 /* UserExpression.cpp */,
+				AEB0E45A1BD6EA1400B24093 /* LLVMUserExpression.h */,
+				AEB0E4581BD6E9F800B24093 /* LLVMUserExpression.cpp */,
 				4C00833D1B9F9B8400D5CF24 /* UtilityFunction.h */,
 				4C00833F1B9F9BA900D5CF24 /* UtilityFunction.cpp */,
 				49A1CAC11430E21D00306AC9 /* ExpressionSourceCode.h */,
@@ -5207,6 +5222,7 @@
 			isa = PBXGroup;
 			children = (
 				4984BA0C1B97620B008658D4 /* Clang */,
+				AE44FB371BB35A2E0033EB62 /* Go */,
 			);
 			name = ExpressionParser;
 			sourceTree = "<group>";
@@ -5580,6 +5596,20 @@
 			name = "SysV-mips";
 			sourceTree = "<group>";
 		};
+		AE44FB371BB35A2E0033EB62 /* Go */ = {
+			isa = PBXGroup;
+			children = (
+				AE44FB261BB07DC60033EB62 /* GoAST.h */,
+				AE44FB271BB07DC60033EB62 /* GoLexer.h */,
+				AE44FB2A1BB07DD80033EB62 /* GoLexer.cpp */,
+				AE44FB281BB07DC60033EB62 /* GoParser.h */,
+				AE44FB2B1BB07DD80033EB62 /* GoParser.cpp */,
+				AE44FB291BB07DC60033EB62 /* GoUserExpression.h */,
+				AE44FB2C1BB07DD80033EB62 /* GoUserExpression.cpp */,
+			);
+			name = Go;
+			sourceTree = "<group>";
+		};
 		AE44FB3B1BB485730033EB62 /* Go */ = {
 			isa = PBXGroup;
 			children = (
@@ -6281,6 +6311,7 @@
 				2689FFDA13353D9D00698AC0 /* lldb.cpp in Sources */,
 				4C0083401B9F9BA900D5CF24 /* UtilityFunction.cpp in Sources */,
 				26474CCD18D0CB5B0073DEBA /* RegisterContextPOSIX_x86.cpp in Sources */,
+				AEB0E4591BD6E9F800B24093 /* LLVMUserExpression.cpp in Sources */,
 				2689FFEF13353DB600698AC0 /* Breakpoint.cpp in Sources */,
 				267A47FB1B1411C40021A5BC /* NativeRegisterContext.cpp in Sources */,
 				2689FFF113353DB600698AC0 /* BreakpointID.cpp in Sources */,
@@ -6410,6 +6441,7 @@
 				3F81691A1ABA2419001DA9DF /* NameMatches.cpp in Sources */,
 				94B9E5121BBF20F4000A48DC /* NSString.cpp in Sources */,
 				AF0E22F018A09FB20009B7D1 /* AppleGetItemInfoHandler.cpp in Sources */,
+				AE44FB301BB07EB20033EB62 /* GoUserExpression.cpp in Sources */,
 				2689004E13353E0400698AC0 /* Stream.cpp in Sources */,
 				2689004F13353E0400698AC0 /* StreamFile.cpp in Sources */,
 				2689005013353E0400698AC0 /* StreamString.cpp in Sources */,
@@ -6528,6 +6560,7 @@
 				949EEDA31BA76577008C63CF /* Cocoa.cpp in Sources */,
 				3FDFE56C19AF9C44009756A7 /* HostProcessPosix.cpp in Sources */,
 				268900B413353E5000698AC0 /* RegisterContextMacOSXFrameBackchain.cpp in Sources */,
+				AE44FB321BB07EBC0033EB62 /* GoParser.cpp in Sources */,
 				3F8169311ABB7A6D001DA9DF /* SystemInitializer.cpp in Sources */,
 				949EEDB21BA76731008C63CF /* NSIndexPath.cpp in Sources */,
 				3FDFED2D19C257A0009756A7 /* HostProcess.cpp in Sources */,
@@ -6689,6 +6722,7 @@
 				26D5E163135BB054006EA0A7 /* OptionGroupPlatform.cpp in Sources */,
 				94CD131A19BA33B400DB7BED /* TypeValidator.cpp in Sources */,
 				26BD407F135D2AE000237D80 /* FileLineResolver.cpp in Sources */,
+				AE44FB311BB07EB80033EB62 /* GoLexer.cpp in Sources */,
 				26A7A035135E6E4200FB369E /* OptionValue.cpp in Sources */,
 				9A22A161135E30370024DDC3 /* EmulateInstructionARM.cpp in Sources */,
 				AFDFDFD119E34D3400EAE509 /* ConnectionFileDescriptorPosix.cpp in Sources */,

Modified: lldb/trunk/source/API/SBFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBFrame.cpp?rev=251820&r1=251819&r2=251820&view=diff
==============================================================================
--- lldb/trunk/source/API/SBFrame.cpp (original)
+++ lldb/trunk/source/API/SBFrame.cpp Mon Nov  2 13:30:40 2015
@@ -1389,6 +1389,10 @@ SBFrame::EvaluateExpression (const char
         lldb::DynamicValueType fetch_dynamic_value = frame->CalculateTarget()->GetPreferDynamicValue();
         options.SetFetchDynamicValue (fetch_dynamic_value);
         options.SetUnwindOnError (true);
+        if (target->GetLanguage() != eLanguageTypeUnknown)
+            options.SetLanguage(target->GetLanguage());
+        else
+            options.SetLanguage(frame->GetLanguage());
         return EvaluateExpression (expr, options);
     }
     return result;
@@ -1400,6 +1404,13 @@ SBFrame::EvaluateExpression (const char
     SBExpressionOptions options;
     options.SetFetchDynamicValue (fetch_dynamic_value);
     options.SetUnwindOnError (true);
+    ExecutionContext exe_ctx(m_opaque_sp.get());
+    StackFrame *frame = exe_ctx.GetFramePtr();
+    Target *target = exe_ctx.GetTargetPtr();
+    if (target && target->GetLanguage() != eLanguageTypeUnknown)
+        options.SetLanguage(target->GetLanguage());
+    else if (frame)
+        options.SetLanguage(frame->GetLanguage());
     return EvaluateExpression (expr, options);
 }
 
@@ -1407,8 +1418,15 @@ SBValue
 SBFrame::EvaluateExpression (const char *expr, lldb::DynamicValueType fetch_dynamic_value, bool unwind_on_error)
 {
     SBExpressionOptions options;
+    ExecutionContext exe_ctx(m_opaque_sp.get());
     options.SetFetchDynamicValue (fetch_dynamic_value);
     options.SetUnwindOnError (unwind_on_error);
+    StackFrame *frame = exe_ctx.GetFramePtr();
+    Target *target = exe_ctx.GetTargetPtr();
+    if (target && target->GetLanguage() != eLanguageTypeUnknown)
+        options.SetLanguage(target->GetLanguage());
+    else if (frame)
+        options.SetLanguage(frame->GetLanguage());
     return EvaluateExpression (expr, options);
 }
 

Modified: lldb/trunk/source/Expression/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/CMakeLists.txt?rev=251820&r1=251819&r2=251820&view=diff
==============================================================================
--- lldb/trunk/source/Expression/CMakeLists.txt (original)
+++ lldb/trunk/source/Expression/CMakeLists.txt Mon Nov  2 13:30:40 2015
@@ -8,6 +8,7 @@ add_lldb_library(lldbExpression
   IRExecutionUnit.cpp
   IRInterpreter.cpp
   IRMemoryMap.cpp
+  LLVMUserExpression.cpp
   Materializer.cpp
   REPL.cpp
   UserExpression.cpp

Added: lldb/trunk/source/Expression/LLVMUserExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/LLVMUserExpression.cpp?rev=251820&view=auto
==============================================================================
--- lldb/trunk/source/Expression/LLVMUserExpression.cpp (added)
+++ lldb/trunk/source/Expression/LLVMUserExpression.cpp Mon Nov  2 13:30:40 2015
@@ -0,0 +1,353 @@
+//===-- LLVMUserExpression.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+
+// Project includes
+#include "lldb/Expression/LLVMUserExpression.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Expression/ExpressionSourceCode.h"
+#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Expression/IRInterpreter.h"
+#include "lldb/Expression/Materializer.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanCallUserExpression.h"
+
+using namespace lldb_private;
+
+LLVMUserExpression::LLVMUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix,
+                                       lldb::LanguageType language, ResultType desired_type)
+    : UserExpression(exe_scope, expr, expr_prefix, language, desired_type),
+      m_stack_frame_bottom(LLDB_INVALID_ADDRESS),
+      m_stack_frame_top(LLDB_INVALID_ADDRESS),
+      m_transformed_text(),
+      m_execution_unit_sp(),
+      m_materializer_ap(),
+      m_jit_module_wp(),
+      m_enforce_valid_object(true),
+      m_in_cplusplus_method(false),
+      m_in_objectivec_method(false),
+      m_in_static_method(false),
+      m_needs_object_ptr(false),
+      m_const_object(false),
+      m_target(NULL),
+      m_can_interpret(false),
+      m_materialized_address(LLDB_INVALID_ADDRESS)
+{
+}
+
+LLVMUserExpression::~LLVMUserExpression()
+{
+    if (m_target)
+    {
+        lldb::ModuleSP jit_module_sp(m_jit_module_wp.lock());
+        if (jit_module_sp)
+            m_target->GetImages().Remove(jit_module_sp);
+    }
+}
+
+lldb::ExpressionResults
+LLVMUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options,
+                            lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result)
+{
+    // The expression log is quite verbose, and if you're just tracking the execution of the
+    // expression, it's quite convenient to have these logs come out with the STEP log as well.
+    Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
+
+    if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
+    {
+        lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;
+
+        if (!PrepareToExecuteJITExpression(error_stream, exe_ctx, struct_address))
+        {
+            error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__);
+            return lldb::eExpressionSetupError;
+        }
+
+        lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS;
+        lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS;
+
+        if (m_can_interpret)
+        {
+            llvm::Module *module = m_execution_unit_sp->GetModule();
+            llvm::Function *function = m_execution_unit_sp->GetFunction();
+
+            if (!module || !function)
+            {
+                error_stream.Printf("Supposed to interpret, but nothing is there");
+                return lldb::eExpressionSetupError;
+            }
+
+            Error interpreter_error;
+
+            std::vector<lldb::addr_t> args;
+
+            if (!AddInitialArguments(exe_ctx, args, error_stream))
+            {
+                error_stream.Printf("Errored out in %s, couldn't AddInitialArguments", __FUNCTION__);
+                return lldb::eExpressionSetupError;
+            }
+
+            args.push_back(struct_address);
+
+            function_stack_bottom = m_stack_frame_bottom;
+            function_stack_top = m_stack_frame_top;
+
+            IRInterpreter::Interpret(*module, *function, args, *m_execution_unit_sp.get(), interpreter_error,
+                                     function_stack_bottom, function_stack_top, exe_ctx);
+
+            if (!interpreter_error.Success())
+            {
+                error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString());
+                return lldb::eExpressionDiscarded;
+            }
+        }
+        else
+        {
+            if (!exe_ctx.HasThreadScope())
+            {
+                error_stream.Printf("UserExpression::Execute called with no thread selected.");
+                return lldb::eExpressionSetupError;
+            }
+
+            Address wrapper_address(m_jit_start_addr);
+
+            std::vector<lldb::addr_t> args;
+
+            if (!AddInitialArguments(exe_ctx, args, error_stream))
+            {
+                error_stream.Printf("Errored out in %s, couldn't AddInitialArguments", __FUNCTION__);
+                return lldb::eExpressionSetupError;
+            }
+
+            args.push_back(struct_address);
+
+            lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression(exe_ctx.GetThreadRef(), wrapper_address,
+                                                                             args, options, shared_ptr_to_me));
+
+            if (!call_plan_sp || !call_plan_sp->ValidatePlan(&error_stream))
+                return lldb::eExpressionSetupError;
+
+            ThreadPlanCallUserExpression *user_expression_plan =
+                static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get());
+
+            lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer();
+
+            function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
+            function_stack_top = function_stack_pointer;
+
+            if (log)
+                log->Printf("-- [UserExpression::Execute] Execution of expression begins --");
+
+            if (exe_ctx.GetProcessPtr())
+                exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
+
+            lldb::ExpressionResults execution_result =
+                exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, error_stream);
+
+            if (exe_ctx.GetProcessPtr())
+                exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
+
+            if (log)
+                log->Printf("-- [UserExpression::Execute] Execution of expression completed --");
+
+            if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint)
+            {
+                const char *error_desc = NULL;
+
+                if (call_plan_sp)
+                {
+                    lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
+                    if (real_stop_info_sp)
+                        error_desc = real_stop_info_sp->GetDescription();
+                }
+                if (error_desc)
+                    error_stream.Printf("Execution was interrupted, reason: %s.", error_desc);
+                else
+                    error_stream.PutCString("Execution was interrupted.");
+
+                if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError()) ||
+                    (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints()))
+                    error_stream.PutCString(
+                        "\nThe process has been returned to the state before expression evaluation.");
+                else
+                {
+                    if (execution_result == lldb::eExpressionHitBreakpoint)
+                        user_expression_plan->TransferExpressionOwnership();
+                    error_stream.PutCString(
+                        "\nThe process has been left at the point where it was interrupted, "
+                        "use \"thread return -x\" to return to the state before expression evaluation.");
+                }
+
+                return execution_result;
+            }
+            else if (execution_result == lldb::eExpressionStoppedForDebug)
+            {
+                error_stream.PutCString(
+                    "Execution was halted at the first instruction of the expression "
+                    "function because \"debug\" was requested.\n"
+                    "Use \"thread return -x\" to return to the state before expression evaluation.");
+                return execution_result;
+            }
+            else if (execution_result != lldb::eExpressionCompleted)
+            {
+                error_stream.Printf("Couldn't execute function; result was %s\n",
+                                    Process::ExecutionResultAsCString(execution_result));
+                return execution_result;
+            }
+        }
+
+        if (FinalizeJITExecution(error_stream, exe_ctx, result, function_stack_bottom, function_stack_top))
+        {
+            return lldb::eExpressionCompleted;
+        }
+        else
+        {
+            return lldb::eExpressionResultUnavailable;
+        }
+    }
+    else
+    {
+        error_stream.Printf("Expression can't be run, because there is no JIT compiled function");
+        return lldb::eExpressionSetupError;
+    }
+}
+
+bool
+LLVMUserExpression::FinalizeJITExecution(Stream &error_stream, ExecutionContext &exe_ctx,
+                                         lldb::ExpressionVariableSP &result, lldb::addr_t function_stack_bottom,
+                                         lldb::addr_t function_stack_top)
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+    if (log)
+        log->Printf("-- [UserExpression::FinalizeJITExecution] Dematerializing after execution --");
+
+    if (!m_dematerializer_sp)
+    {
+        error_stream.Printf("Couldn't apply expression side effects : no dematerializer is present");
+        return false;
+    }
+
+    Error dematerialize_error;
+
+    m_dematerializer_sp->Dematerialize(dematerialize_error, function_stack_bottom, function_stack_top);
+
+    if (!dematerialize_error.Success())
+    {
+        error_stream.Printf("Couldn't apply expression side effects : %s\n",
+                            dematerialize_error.AsCString("unknown error"));
+        return false;
+    }
+
+    result = GetResultAfterDematerialization(exe_ctx.GetBestExecutionContextScope());
+
+    if (result)
+        result->TransferAddress();
+
+    m_dematerializer_sp.reset();
+
+    return true;
+}
+
+bool
+LLVMUserExpression::PrepareToExecuteJITExpression(Stream &error_stream, ExecutionContext &exe_ctx,
+                                                  lldb::addr_t &struct_address)
+{
+    lldb::TargetSP target;
+    lldb::ProcessSP process;
+    lldb::StackFrameSP frame;
+
+    if (!LockAndCheckContext(exe_ctx, target, process, frame))
+    {
+        error_stream.Printf("The context has changed before we could JIT the expression!\n");
+        return false;
+    }
+
+    if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
+    {
+        if (m_materialized_address == LLDB_INVALID_ADDRESS)
+        {
+            Error alloc_error;
+
+            IRMemoryMap::AllocationPolicy policy =
+                m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly : IRMemoryMap::eAllocationPolicyMirror;
+
+            m_materialized_address = m_execution_unit_sp->Malloc(
+                m_materializer_ap->GetStructByteSize(), m_materializer_ap->GetStructAlignment(),
+                lldb::ePermissionsReadable | lldb::ePermissionsWritable, policy, alloc_error);
+
+            if (!alloc_error.Success())
+            {
+                error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString());
+                return false;
+            }
+        }
+
+        struct_address = m_materialized_address;
+
+        if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS)
+        {
+            Error alloc_error;
+
+            const size_t stack_frame_size = 512 * 1024;
+
+            m_stack_frame_bottom = m_execution_unit_sp->Malloc(stack_frame_size, 8,
+                                                               lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+                                                               IRMemoryMap::eAllocationPolicyHostOnly, alloc_error);
+
+            m_stack_frame_top = m_stack_frame_bottom + stack_frame_size;
+
+            if (!alloc_error.Success())
+            {
+                error_stream.Printf("Couldn't allocate space for the stack frame: %s\n", alloc_error.AsCString());
+                return false;
+            }
+        }
+
+        Error materialize_error;
+
+        m_dematerializer_sp =
+            m_materializer_ap->Materialize(frame, *m_execution_unit_sp, struct_address, materialize_error);
+
+        if (!materialize_error.Success())
+        {
+            error_stream.Printf("Couldn't materialize: %s\n", materialize_error.AsCString());
+            return false;
+        }
+    }
+    return true;
+}
+
+lldb::ModuleSP
+LLVMUserExpression::GetJITModule()
+{
+    if (m_execution_unit_sp)
+        return m_execution_unit_sp->GetJITModule();
+    return lldb::ModuleSP();
+}

Modified: lldb/trunk/source/Expression/UserExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/UserExpression.cpp?rev=251820&r1=251819&r2=251820&view=diff
==============================================================================
--- lldb/trunk/source/Expression/UserExpression.cpp (original)
+++ lldb/trunk/source/Expression/UserExpression.cpp Mon Nov  2 13:30:40 2015
@@ -45,42 +45,18 @@
 
 using namespace lldb_private;
 
-UserExpression::UserExpression (ExecutionContextScope &exe_scope,
-                                const char *expr,
-                                const char *expr_prefix,
-                                lldb::LanguageType language,
-                                ResultType desired_type) :
-    Expression (exe_scope),
-    m_stack_frame_bottom (LLDB_INVALID_ADDRESS),
-    m_stack_frame_top (LLDB_INVALID_ADDRESS),
-    m_expr_text (expr),
-    m_expr_prefix (expr_prefix ? expr_prefix : ""),
-    m_language (language),
-    m_transformed_text (),
-    m_desired_type (desired_type),
-    m_execution_unit_sp(),
-    m_materializer_ap(),
-    m_jit_module_wp(),
-    m_enforce_valid_object (true),
-    m_in_cplusplus_method (false),
-    m_in_objectivec_method (false),
-    m_in_static_method(false),
-    m_needs_object_ptr (false),
-    m_const_object (false),
-    m_target (NULL),
-    m_can_interpret (false),
-    m_materialized_address (LLDB_INVALID_ADDRESS)
+UserExpression::UserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix,
+                               lldb::LanguageType language, ResultType desired_type)
+    : Expression(exe_scope),
+      m_expr_text(expr),
+      m_expr_prefix(expr_prefix ? expr_prefix : ""),
+      m_language(language),
+      m_desired_type(desired_type)
 {
 }
 
 UserExpression::~UserExpression ()
 {
-    if (m_target)
-    {
-        lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock());
-        if (jit_module_sp)
-            m_target->GetImages().Remove(jit_module_sp);
-    }
 }
 
 void
@@ -170,295 +146,6 @@ UserExpression::GetObjectPointer (lldb::
     return ret;
 }
 
-bool
-UserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
-                                                    ExecutionContext &exe_ctx,
-                                                    lldb::addr_t &struct_address)
-{
-    lldb::TargetSP target;
-    lldb::ProcessSP process;
-    lldb::StackFrameSP frame;
-
-    if (!LockAndCheckContext(exe_ctx,
-                             target,
-                             process,
-                             frame))
-    {
-        error_stream.Printf("The context has changed before we could JIT the expression!\n");
-        return false;
-    }
-
-    if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
-    {
-        if (m_materialized_address == LLDB_INVALID_ADDRESS)
-        {
-            Error alloc_error;
-
-            IRMemoryMap::AllocationPolicy policy = m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly : IRMemoryMap::eAllocationPolicyMirror;
-
-            m_materialized_address = m_execution_unit_sp->Malloc(m_materializer_ap->GetStructByteSize(),
-                                                                 m_materializer_ap->GetStructAlignment(),
-                                                                 lldb::ePermissionsReadable | lldb::ePermissionsWritable,
-                                                                 policy,
-                                                                 alloc_error);
-
-            if (!alloc_error.Success())
-            {
-                error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString());
-                return false;
-            }
-        }
-
-        struct_address = m_materialized_address;
-
-        if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS)
-        {
-            Error alloc_error;
-
-            const size_t stack_frame_size = 512 * 1024;
-
-            m_stack_frame_bottom = m_execution_unit_sp->Malloc(stack_frame_size,
-                                                               8,
-                                                               lldb::ePermissionsReadable | lldb::ePermissionsWritable,
-                                                               IRMemoryMap::eAllocationPolicyHostOnly,
-                                                               alloc_error);
-
-            m_stack_frame_top = m_stack_frame_bottom + stack_frame_size;
-
-            if (!alloc_error.Success())
-            {
-                error_stream.Printf("Couldn't allocate space for the stack frame: %s\n", alloc_error.AsCString());
-                return false;
-            }
-        }
-
-        Error materialize_error;
-
-        m_dematerializer_sp = m_materializer_ap->Materialize(frame, *m_execution_unit_sp, struct_address, materialize_error);
-
-        if (!materialize_error.Success())
-        {
-            error_stream.Printf("Couldn't materialize: %s\n", materialize_error.AsCString());
-            return false;
-        }
-    }
-    return true;
-}
-
-bool
-UserExpression::FinalizeJITExecution (Stream &error_stream,
-                                           ExecutionContext &exe_ctx,
-                                           lldb::ExpressionVariableSP &result,
-                                           lldb::addr_t function_stack_bottom,
-                                           lldb::addr_t function_stack_top)
-{
-    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
-    if (log)
-        log->Printf("-- [UserExpression::FinalizeJITExecution] Dematerializing after execution --");
-
-    if (!m_dematerializer_sp)
-    {
-        error_stream.Printf ("Couldn't apply expression side effects : no dematerializer is present");
-        return false;
-    }
-
-    Error dematerialize_error;
-
-    m_dematerializer_sp->Dematerialize(dematerialize_error, function_stack_bottom, function_stack_top);
-
-    if (!dematerialize_error.Success())
-    {
-        error_stream.Printf ("Couldn't apply expression side effects : %s\n", dematerialize_error.AsCString("unknown error"));
-        return false;
-    }
-
-    result = GetResultAfterDematerialization(exe_ctx.GetBestExecutionContextScope());
-    
-    if (result)
-        result->TransferAddress();
-
-    m_dematerializer_sp.reset();
-
-    return true;
-}
-
-lldb::ExpressionResults
-UserExpression::Execute (Stream &error_stream,
-                              ExecutionContext &exe_ctx,
-                              const EvaluateExpressionOptions& options,
-                              lldb::UserExpressionSP &shared_ptr_to_me,
-                              lldb::ExpressionVariableSP &result)
-{
-    // The expression log is quite verbose, and if you're just tracking the execution of the
-    // expression, it's quite convenient to have these logs come out with the STEP log as well.
-    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
-
-    if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
-    {
-        lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;
-
-        if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address))
-        {
-            error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__);
-            return lldb::eExpressionSetupError;
-        }
-
-        lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS;
-        lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS;
-
-        if (m_can_interpret)
-        {
-            llvm::Module *module = m_execution_unit_sp->GetModule();
-            llvm::Function *function = m_execution_unit_sp->GetFunction();
-
-            if (!module || !function)
-            {
-                error_stream.Printf("Supposed to interpret, but nothing is there");
-                return lldb::eExpressionSetupError;
-            }
-
-            Error interpreter_error;
-
-            std::vector<lldb::addr_t> args;
-            
-            if (!AddInitialArguments(exe_ctx, args, error_stream))
-            {
-                error_stream.Printf ("Errored out in %s, couldn't AddInitialArguments", __FUNCTION__);
-                return lldb::eExpressionSetupError;
-            }
-            
-            args.push_back(struct_address);
-
-            function_stack_bottom = m_stack_frame_bottom;
-            function_stack_top = m_stack_frame_top;
-
-            IRInterpreter::Interpret (*module,
-                                      *function,
-                                      args,
-                                      *m_execution_unit_sp.get(),
-                                      interpreter_error,
-                                      function_stack_bottom,
-                                      function_stack_top,
-                                      exe_ctx);
-
-            if (!interpreter_error.Success())
-            {
-                error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString());
-                return lldb::eExpressionDiscarded;
-            }
-        }
-        else
-        {
-            if (!exe_ctx.HasThreadScope())
-            {
-                error_stream.Printf("UserExpression::Execute called with no thread selected.");
-                return lldb::eExpressionSetupError;
-            }
-
-            Address wrapper_address (m_jit_start_addr);
-
-            std::vector<lldb::addr_t> args;
-            
-            if (!AddInitialArguments(exe_ctx, args, error_stream))
-            {
-                error_stream.Printf ("Errored out in %s, couldn't AddInitialArguments", __FUNCTION__);
-                return lldb::eExpressionSetupError;
-            }
-
-            args.push_back(struct_address);
-         
-            lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
-                                                                              wrapper_address,
-                                                                              args,
-                                                                              options,
-                                                                              shared_ptr_to_me));
-
-            if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream))
-                return lldb::eExpressionSetupError;
-
-            ThreadPlanCallUserExpression *user_expression_plan = static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get());
-
-            lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer();
-
-            function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
-            function_stack_top = function_stack_pointer;
-
-            if (log)
-                log->Printf("-- [UserExpression::Execute] Execution of expression begins --");
-
-            if (exe_ctx.GetProcessPtr())
-                exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
-
-            lldb::ExpressionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx,
-                                                                                       call_plan_sp,
-                                                                                       options,
-                                                                                       error_stream);
-
-            if (exe_ctx.GetProcessPtr())
-                exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
-
-            if (log)
-                log->Printf("-- [UserExpression::Execute] Execution of expression completed --");
-
-            if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint)
-            {
-                const char *error_desc = NULL;
-
-                if (call_plan_sp)
-                {
-                    lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
-                    if (real_stop_info_sp)
-                        error_desc = real_stop_info_sp->GetDescription();
-                }
-                if (error_desc)
-                    error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc);
-                else
-                    error_stream.PutCString ("Execution was interrupted.");
-
-                if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError())
-                    || (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints()))
-                    error_stream.PutCString ("\nThe process has been returned to the state before expression evaluation.");
-                else
-                {
-                    if (execution_result == lldb::eExpressionHitBreakpoint)
-                        user_expression_plan->TransferExpressionOwnership();
-                    error_stream.PutCString ("\nThe process has been left at the point where it was interrupted, "
-                                             "use \"thread return -x\" to return to the state before expression evaluation.");
-                }
-
-                return execution_result;
-            }
-            else if (execution_result == lldb::eExpressionStoppedForDebug)
-            {
-                    error_stream.PutCString ("Execution was halted at the first instruction of the expression "
-                                             "function because \"debug\" was requested.\n"
-                                             "Use \"thread return -x\" to return to the state before expression evaluation.");
-                    return execution_result;
-            }
-            else if (execution_result != lldb::eExpressionCompleted)
-            {
-                error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
-                return execution_result;
-            }
-        }
-
-        if  (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_bottom, function_stack_top))
-        {
-            return lldb::eExpressionCompleted;
-        }
-        else
-        {
-            return lldb::eExpressionResultUnavailable;
-        }
-    }
-    else
-    {
-        error_stream.Printf("Expression can't be run, because there is no JIT compiled function");
-        return lldb::eExpressionSetupError;
-    }
-}
-
 lldb::ExpressionResults
 UserExpression::Evaluate (ExecutionContext &exe_ctx,
                                const EvaluateExpressionOptions& options,
@@ -570,8 +257,8 @@ UserExpression::Evaluate (ExecutionConte
     else
     {
         // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created
-        if (jit_module_sp_ptr && user_expression_sp->m_execution_unit_sp)
-            *jit_module_sp_ptr = user_expression_sp->m_execution_unit_sp->GetJITModule();
+        if (jit_module_sp_ptr)
+            *jit_module_sp_ptr = user_expression_sp->GetJITModule();
 
         lldb::ExpressionVariableSP expr_result;
 

Modified: lldb/trunk/source/Plugins/ExpressionParser/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/CMakeLists.txt?rev=251820&r1=251819&r2=251820&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/ExpressionParser/CMakeLists.txt Mon Nov  2 13:30:40 2015
@@ -1 +1,2 @@
 add_subdirectory(Clang)
+add_subdirectory(Go)

Modified: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp?rev=251820&r1=251819&r2=251820&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp (original)
+++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp Mon Nov  2 13:30:40 2015
@@ -55,13 +55,10 @@
 
 using namespace lldb_private;
 
-ClangUserExpression::ClangUserExpression (ExecutionContextScope &exe_scope,
-                                          const char *expr,
-                                          const char *expr_prefix,
-                                          lldb::LanguageType language,
-                                          ResultType desired_type) :
-    UserExpression (exe_scope, expr, expr_prefix, language, desired_type),
-    m_type_system_helper(*m_target_wp.lock().get())
+ClangUserExpression::ClangUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix,
+                                         lldb::LanguageType language, ResultType desired_type)
+    : LLVMUserExpression(exe_scope, expr, expr_prefix, language, desired_type),
+      m_type_system_helper(*m_target_wp.lock().get())
 {
     switch (m_language)
     {

Modified: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h?rev=251820&r1=251819&r2=251820&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h (original)
+++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h Mon Nov  2 13:30:40 2015
@@ -27,7 +27,7 @@
 #include "lldb/lldb-private.h"
 #include "lldb/Core/Address.h"
 #include "lldb/Core/ClangForward.h"
-#include "lldb/Expression/UserExpression.h"
+#include "lldb/Expression/LLVMUserExpression.h"
 #include "lldb/Expression/Materializer.h"
 #include "lldb/Target/ExecutionContext.h"
 
@@ -43,7 +43,7 @@ namespace lldb_private
 /// the objects needed to parse and interpret or JIT an expression.  It
 /// uses the Clang parser to produce LLVM IR from the expression.
 //----------------------------------------------------------------------
-class ClangUserExpression : public UserExpression
+class ClangUserExpression : public LLVMUserExpression
 {
 public:
     enum { kDefaultTimeout = 500000u };

Added: lldb/trunk/source/Plugins/ExpressionParser/Go/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Go/CMakeLists.txt?rev=251820&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Go/CMakeLists.txt (added)
+++ lldb/trunk/source/Plugins/ExpressionParser/Go/CMakeLists.txt Mon Nov  2 13:30:40 2015
@@ -0,0 +1,5 @@
+add_lldb_library(lldbPluginExpressionParserGo
+	GoLexer.cpp
+	GoParser.cpp
+	GoUserExpression.cpp
+  )

Added: lldb/trunk/source/Plugins/ExpressionParser/Go/GoAST.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Go/GoAST.h?rev=251820&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Go/GoAST.h (added)
+++ lldb/trunk/source/Plugins/ExpressionParser/Go/GoAST.h Mon Nov  2 13:30:40 2015
@@ -0,0 +1,3225 @@
+//===-- GoAST.h -------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// DO NOT EDIT.
+// Generated by gen_go_ast.py
+
+#ifndef liblldb_GoAST_h
+#define liblldb_GoAST_h
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+#include "llvm/Support/Casting.h"
+#include "Plugins/ExpressionParser/Go/GoLexer.h"
+
+namespace lldb_private
+{
+
+class GoASTNode
+{
+  public:
+    typedef GoLexer::TokenType TokenType;
+    typedef GoLexer::Token Token;
+    enum ChanDir
+    {
+        eChanBidir,
+        eChanSend,
+        eChanRecv,
+    };
+    enum NodeKind
+    {
+        eBadDecl,
+        eFuncDecl,
+        eGenDecl,
+        eArrayType,
+        eBadExpr,
+        eBasicLit,
+        eBinaryExpr,
+        eIdent,
+        eCallExpr,
+        eChanType,
+        eCompositeLit,
+        eEllipsis,
+        eFuncType,
+        eFuncLit,
+        eIndexExpr,
+        eInterfaceType,
+        eKeyValueExpr,
+        eMapType,
+        eParenExpr,
+        eSelectorExpr,
+        eSliceExpr,
+        eStarExpr,
+        eStructType,
+        eTypeAssertExpr,
+        eUnaryExpr,
+        eImportSpec,
+        eTypeSpec,
+        eValueSpec,
+        eAssignStmt,
+        eBadStmt,
+        eBlockStmt,
+        eBranchStmt,
+        eCaseClause,
+        eCommClause,
+        eDeclStmt,
+        eDeferStmt,
+        eEmptyStmt,
+        eExprStmt,
+        eForStmt,
+        eGoStmt,
+        eIfStmt,
+        eIncDecStmt,
+        eLabeledStmt,
+        eRangeStmt,
+        eReturnStmt,
+        eSelectStmt,
+        eSendStmt,
+        eSwitchStmt,
+        eTypeSwitchStmt,
+        eField,
+        eFieldList,
+    };
+
+    virtual ~GoASTNode() = default;
+
+    NodeKind
+    GetKind() const
+    {
+        return m_kind;
+    }
+
+    virtual const char *GetKindName() const = 0;
+
+    template <typename V> void WalkChildren(V &v);
+
+  protected:
+    explicit GoASTNode(NodeKind kind) : m_kind(kind) { }
+
+  private:
+    const NodeKind m_kind;
+    
+    GoASTNode(const GoASTNode &) = delete;
+    const GoASTNode &operator=(const GoASTNode &) = delete;
+};
+
+
+class GoASTDecl : public GoASTNode
+{
+  public:
+    template <typename R, typename V> R Visit(V *v) const;
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() >= eBadDecl && n->GetKind() <= eGenDecl;
+    }
+
+  protected:
+    explicit GoASTDecl(NodeKind kind) : GoASTNode(kind) { }
+  private:
+
+    GoASTDecl(const GoASTDecl &) = delete;
+    const GoASTDecl &operator=(const GoASTDecl &) = delete;
+};
+
+class GoASTExpr : public GoASTNode
+{
+  public:
+    template <typename R, typename V> R Visit(V *v) const;
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() >= eArrayType && n->GetKind() <= eUnaryExpr;
+    }
+
+  protected:
+    explicit GoASTExpr(NodeKind kind) : GoASTNode(kind) { }
+  private:
+
+    GoASTExpr(const GoASTExpr &) = delete;
+    const GoASTExpr &operator=(const GoASTExpr &) = delete;
+};
+
+class GoASTSpec : public GoASTNode
+{
+  public:
+    template <typename R, typename V> R Visit(V *v) const;
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() >= eImportSpec && n->GetKind() <= eValueSpec;
+    }
+
+  protected:
+    explicit GoASTSpec(NodeKind kind) : GoASTNode(kind) { }
+  private:
+
+    GoASTSpec(const GoASTSpec &) = delete;
+    const GoASTSpec &operator=(const GoASTSpec &) = delete;
+};
+
+class GoASTStmt : public GoASTNode
+{
+  public:
+    template <typename R, typename V> R Visit(V *v) const;
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() >= eAssignStmt && n->GetKind() <= eTypeSwitchStmt;
+    }
+
+  protected:
+    explicit GoASTStmt(NodeKind kind) : GoASTNode(kind) { }
+  private:
+
+    GoASTStmt(const GoASTStmt &) = delete;
+    const GoASTStmt &operator=(const GoASTStmt &) = delete;
+};
+
+
+class GoASTArrayType : public GoASTExpr
+{
+  public:
+    GoASTArrayType(GoASTExpr *len, GoASTExpr *elt) : GoASTExpr(eArrayType), m_len_up(len), m_elt_up(elt) {}
+    ~GoASTArrayType() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "ArrayType";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eArrayType;
+    }
+    
+    const GoASTExpr *
+    GetLen() const
+    {
+        return m_len_up.get();
+    }
+    void
+    SetLen(GoASTExpr *len)
+    {
+        m_len_up.reset(len);
+    }
+
+    const GoASTExpr *
+    GetElt() const
+    {
+        return m_elt_up.get();
+    }
+    void
+    SetElt(GoASTExpr *elt)
+    {
+        m_elt_up.reset(elt);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTExpr> m_len_up;
+    std::unique_ptr<GoASTExpr> m_elt_up;
+
+    GoASTArrayType(const GoASTArrayType &) = delete;
+    const GoASTArrayType &operator=(const GoASTArrayType &) = delete;
+};
+
+class GoASTAssignStmt : public GoASTStmt
+{
+  public:
+    explicit GoASTAssignStmt(bool define) : GoASTStmt(eAssignStmt), m_define(define) {}
+    ~GoASTAssignStmt() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "AssignStmt";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eAssignStmt;
+    }
+    
+    size_t
+    NumLhs() const
+    {
+        return m_lhs.size();
+    }
+    const GoASTExpr *
+    GetLhs(int i) const
+    {
+        return m_lhs[i].get();
+    }
+    void
+    AddLhs(GoASTExpr *lhs)
+    {
+        m_lhs.push_back(std::unique_ptr<GoASTExpr>(lhs));
+    }
+
+    size_t
+    NumRhs() const
+    {
+        return m_rhs.size();
+    }
+    const GoASTExpr *
+    GetRhs(int i) const
+    {
+        return m_rhs[i].get();
+    }
+    void
+    AddRhs(GoASTExpr *rhs)
+    {
+        m_rhs.push_back(std::unique_ptr<GoASTExpr>(rhs));
+    }
+
+    bool 
+    GetDefine() const
+    {
+        return m_define;
+    }
+    void
+    SetDefine(bool define)
+    {
+        m_define = define;
+    }
+
+  private:
+    friend class GoASTNode;
+    std::vector<std::unique_ptr<GoASTExpr> > m_lhs;
+    std::vector<std::unique_ptr<GoASTExpr> > m_rhs;
+    bool m_define;
+
+    GoASTAssignStmt(const GoASTAssignStmt &) = delete;
+    const GoASTAssignStmt &operator=(const GoASTAssignStmt &) = delete;
+};
+
+class GoASTBadDecl : public GoASTDecl
+{
+  public:
+    GoASTBadDecl() : GoASTDecl(eBadDecl) {}
+    ~GoASTBadDecl() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "BadDecl";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eBadDecl;
+    }
+    
+    GoASTBadDecl(const GoASTBadDecl &) = delete;
+    const GoASTBadDecl &operator=(const GoASTBadDecl &) = delete;
+};
+
+class GoASTBadExpr : public GoASTExpr
+{
+  public:
+    GoASTBadExpr() : GoASTExpr(eBadExpr) {}
+    ~GoASTBadExpr() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "BadExpr";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eBadExpr;
+    }
+    
+    GoASTBadExpr(const GoASTBadExpr &) = delete;
+    const GoASTBadExpr &operator=(const GoASTBadExpr &) = delete;
+};
+
+class GoASTBadStmt : public GoASTStmt
+{
+  public:
+    GoASTBadStmt() : GoASTStmt(eBadStmt) {}
+    ~GoASTBadStmt() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "BadStmt";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eBadStmt;
+    }
+    
+    GoASTBadStmt(const GoASTBadStmt &) = delete;
+    const GoASTBadStmt &operator=(const GoASTBadStmt &) = delete;
+};
+
+class GoASTBasicLit : public GoASTExpr
+{
+  public:
+    explicit GoASTBasicLit(Token value) : GoASTExpr(eBasicLit), m_value(value) {}
+    ~GoASTBasicLit() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "BasicLit";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eBasicLit;
+    }
+    
+    Token 
+    GetValue() const
+    {
+        return m_value;
+    }
+    void
+    SetValue(Token value)
+    {
+        m_value = value;
+    }
+
+  private:
+    friend class GoASTNode;
+    Token m_value;
+
+    GoASTBasicLit(const GoASTBasicLit &) = delete;
+    const GoASTBasicLit &operator=(const GoASTBasicLit &) = delete;
+};
+
+class GoASTBinaryExpr : public GoASTExpr
+{
+  public:
+    GoASTBinaryExpr(GoASTExpr *x, GoASTExpr *y, TokenType op) : GoASTExpr(eBinaryExpr), m_x_up(x), m_y_up(y), m_op(op) {}
+    ~GoASTBinaryExpr() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "BinaryExpr";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eBinaryExpr;
+    }
+    
+    const GoASTExpr *
+    GetX() const
+    {
+        return m_x_up.get();
+    }
+    void
+    SetX(GoASTExpr *x)
+    {
+        m_x_up.reset(x);
+    }
+
+    const GoASTExpr *
+    GetY() const
+    {
+        return m_y_up.get();
+    }
+    void
+    SetY(GoASTExpr *y)
+    {
+        m_y_up.reset(y);
+    }
+
+    TokenType 
+    GetOp() const
+    {
+        return m_op;
+    }
+    void
+    SetOp(TokenType op)
+    {
+        m_op = op;
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTExpr> m_x_up;
+    std::unique_ptr<GoASTExpr> m_y_up;
+    TokenType m_op;
+
+    GoASTBinaryExpr(const GoASTBinaryExpr &) = delete;
+    const GoASTBinaryExpr &operator=(const GoASTBinaryExpr &) = delete;
+};
+
+class GoASTBlockStmt : public GoASTStmt
+{
+  public:
+    GoASTBlockStmt() : GoASTStmt(eBlockStmt) {}
+    ~GoASTBlockStmt() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "BlockStmt";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eBlockStmt;
+    }
+    
+    size_t
+    NumList() const
+    {
+        return m_list.size();
+    }
+    const GoASTStmt *
+    GetList(int i) const
+    {
+        return m_list[i].get();
+    }
+    void
+    AddList(GoASTStmt *list)
+    {
+        m_list.push_back(std::unique_ptr<GoASTStmt>(list));
+    }
+
+  private:
+    friend class GoASTNode;
+    std::vector<std::unique_ptr<GoASTStmt> > m_list;
+
+    GoASTBlockStmt(const GoASTBlockStmt &) = delete;
+    const GoASTBlockStmt &operator=(const GoASTBlockStmt &) = delete;
+};
+
+class GoASTIdent : public GoASTExpr
+{
+  public:
+    explicit GoASTIdent(Token name) : GoASTExpr(eIdent), m_name(name) {}
+    ~GoASTIdent() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "Ident";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eIdent;
+    }
+    
+    Token 
+    GetName() const
+    {
+        return m_name;
+    }
+    void
+    SetName(Token name)
+    {
+        m_name = name;
+    }
+
+  private:
+    friend class GoASTNode;
+    Token m_name;
+
+    GoASTIdent(const GoASTIdent &) = delete;
+    const GoASTIdent &operator=(const GoASTIdent &) = delete;
+};
+
+class GoASTBranchStmt : public GoASTStmt
+{
+  public:
+    GoASTBranchStmt(GoASTIdent *label, TokenType tok) : GoASTStmt(eBranchStmt), m_label_up(label), m_tok(tok) {}
+    ~GoASTBranchStmt() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "BranchStmt";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eBranchStmt;
+    }
+    
+    const GoASTIdent *
+    GetLabel() const
+    {
+        return m_label_up.get();
+    }
+    void
+    SetLabel(GoASTIdent *label)
+    {
+        m_label_up.reset(label);
+    }
+
+    TokenType 
+    GetTok() const
+    {
+        return m_tok;
+    }
+    void
+    SetTok(TokenType tok)
+    {
+        m_tok = tok;
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTIdent> m_label_up;
+    TokenType m_tok;
+
+    GoASTBranchStmt(const GoASTBranchStmt &) = delete;
+    const GoASTBranchStmt &operator=(const GoASTBranchStmt &) = delete;
+};
+
+class GoASTCallExpr : public GoASTExpr
+{
+  public:
+    explicit GoASTCallExpr(bool ellipsis) : GoASTExpr(eCallExpr), m_ellipsis(ellipsis) {}
+    ~GoASTCallExpr() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "CallExpr";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eCallExpr;
+    }
+    
+    const GoASTExpr *
+    GetFun() const
+    {
+        return m_fun_up.get();
+    }
+    void
+    SetFun(GoASTExpr *fun)
+    {
+        m_fun_up.reset(fun);
+    }
+
+    size_t
+    NumArgs() const
+    {
+        return m_args.size();
+    }
+    const GoASTExpr *
+    GetArgs(int i) const
+    {
+        return m_args[i].get();
+    }
+    void
+    AddArgs(GoASTExpr *args)
+    {
+        m_args.push_back(std::unique_ptr<GoASTExpr>(args));
+    }
+
+    bool 
+    GetEllipsis() const
+    {
+        return m_ellipsis;
+    }
+    void
+    SetEllipsis(bool ellipsis)
+    {
+        m_ellipsis = ellipsis;
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTExpr> m_fun_up;
+    std::vector<std::unique_ptr<GoASTExpr> > m_args;
+    bool m_ellipsis;
+
+    GoASTCallExpr(const GoASTCallExpr &) = delete;
+    const GoASTCallExpr &operator=(const GoASTCallExpr &) = delete;
+};
+
+class GoASTCaseClause : public GoASTStmt
+{
+  public:
+    GoASTCaseClause() : GoASTStmt(eCaseClause) {}
+    ~GoASTCaseClause() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "CaseClause";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eCaseClause;
+    }
+    
+    size_t
+    NumList() const
+    {
+        return m_list.size();
+    }
+    const GoASTExpr *
+    GetList(int i) const
+    {
+        return m_list[i].get();
+    }
+    void
+    AddList(GoASTExpr *list)
+    {
+        m_list.push_back(std::unique_ptr<GoASTExpr>(list));
+    }
+
+    size_t
+    NumBody() const
+    {
+        return m_body.size();
+    }
+    const GoASTStmt *
+    GetBody(int i) const
+    {
+        return m_body[i].get();
+    }
+    void
+    AddBody(GoASTStmt *body)
+    {
+        m_body.push_back(std::unique_ptr<GoASTStmt>(body));
+    }
+
+  private:
+    friend class GoASTNode;
+    std::vector<std::unique_ptr<GoASTExpr> > m_list;
+    std::vector<std::unique_ptr<GoASTStmt> > m_body;
+
+    GoASTCaseClause(const GoASTCaseClause &) = delete;
+    const GoASTCaseClause &operator=(const GoASTCaseClause &) = delete;
+};
+
+class GoASTChanType : public GoASTExpr
+{
+  public:
+    GoASTChanType(ChanDir dir, GoASTExpr *value) : GoASTExpr(eChanType), m_dir(dir), m_value_up(value) {}
+    ~GoASTChanType() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "ChanType";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eChanType;
+    }
+    
+    ChanDir 
+    GetDir() const
+    {
+        return m_dir;
+    }
+    void
+    SetDir(ChanDir dir)
+    {
+        m_dir = dir;
+    }
+
+    const GoASTExpr *
+    GetValue() const
+    {
+        return m_value_up.get();
+    }
+    void
+    SetValue(GoASTExpr *value)
+    {
+        m_value_up.reset(value);
+    }
+
+  private:
+    friend class GoASTNode;
+    ChanDir m_dir;
+    std::unique_ptr<GoASTExpr> m_value_up;
+
+    GoASTChanType(const GoASTChanType &) = delete;
+    const GoASTChanType &operator=(const GoASTChanType &) = delete;
+};
+
+class GoASTCommClause : public GoASTStmt
+{
+  public:
+    GoASTCommClause() : GoASTStmt(eCommClause) {}
+    ~GoASTCommClause() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "CommClause";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eCommClause;
+    }
+    
+    const GoASTStmt *
+    GetComm() const
+    {
+        return m_comm_up.get();
+    }
+    void
+    SetComm(GoASTStmt *comm)
+    {
+        m_comm_up.reset(comm);
+    }
+
+    size_t
+    NumBody() const
+    {
+        return m_body.size();
+    }
+    const GoASTStmt *
+    GetBody(int i) const
+    {
+        return m_body[i].get();
+    }
+    void
+    AddBody(GoASTStmt *body)
+    {
+        m_body.push_back(std::unique_ptr<GoASTStmt>(body));
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTStmt> m_comm_up;
+    std::vector<std::unique_ptr<GoASTStmt> > m_body;
+
+    GoASTCommClause(const GoASTCommClause &) = delete;
+    const GoASTCommClause &operator=(const GoASTCommClause &) = delete;
+};
+
+class GoASTCompositeLit : public GoASTExpr
+{
+  public:
+    GoASTCompositeLit() : GoASTExpr(eCompositeLit) {}
+    ~GoASTCompositeLit() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "CompositeLit";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eCompositeLit;
+    }
+    
+    const GoASTExpr *
+    GetType() const
+    {
+        return m_type_up.get();
+    }
+    void
+    SetType(GoASTExpr *type)
+    {
+        m_type_up.reset(type);
+    }
+
+    size_t
+    NumElts() const
+    {
+        return m_elts.size();
+    }
+    const GoASTExpr *
+    GetElts(int i) const
+    {
+        return m_elts[i].get();
+    }
+    void
+    AddElts(GoASTExpr *elts)
+    {
+        m_elts.push_back(std::unique_ptr<GoASTExpr>(elts));
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTExpr> m_type_up;
+    std::vector<std::unique_ptr<GoASTExpr> > m_elts;
+
+    GoASTCompositeLit(const GoASTCompositeLit &) = delete;
+    const GoASTCompositeLit &operator=(const GoASTCompositeLit &) = delete;
+};
+
+class GoASTDeclStmt : public GoASTStmt
+{
+  public:
+    explicit GoASTDeclStmt(GoASTDecl *decl) : GoASTStmt(eDeclStmt), m_decl_up(decl) {}
+    ~GoASTDeclStmt() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "DeclStmt";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eDeclStmt;
+    }
+    
+    const GoASTDecl *
+    GetDecl() const
+    {
+        return m_decl_up.get();
+    }
+    void
+    SetDecl(GoASTDecl *decl)
+    {
+        m_decl_up.reset(decl);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTDecl> m_decl_up;
+
+    GoASTDeclStmt(const GoASTDeclStmt &) = delete;
+    const GoASTDeclStmt &operator=(const GoASTDeclStmt &) = delete;
+};
+
+class GoASTDeferStmt : public GoASTStmt
+{
+  public:
+    explicit GoASTDeferStmt(GoASTCallExpr *call) : GoASTStmt(eDeferStmt), m_call_up(call) {}
+    ~GoASTDeferStmt() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "DeferStmt";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eDeferStmt;
+    }
+    
+    const GoASTCallExpr *
+    GetCall() const
+    {
+        return m_call_up.get();
+    }
+    void
+    SetCall(GoASTCallExpr *call)
+    {
+        m_call_up.reset(call);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTCallExpr> m_call_up;
+
+    GoASTDeferStmt(const GoASTDeferStmt &) = delete;
+    const GoASTDeferStmt &operator=(const GoASTDeferStmt &) = delete;
+};
+
+class GoASTEllipsis : public GoASTExpr
+{
+  public:
+    explicit GoASTEllipsis(GoASTExpr *elt) : GoASTExpr(eEllipsis), m_elt_up(elt) {}
+    ~GoASTEllipsis() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "Ellipsis";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eEllipsis;
+    }
+    
+    const GoASTExpr *
+    GetElt() const
+    {
+        return m_elt_up.get();
+    }
+    void
+    SetElt(GoASTExpr *elt)
+    {
+        m_elt_up.reset(elt);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTExpr> m_elt_up;
+
+    GoASTEllipsis(const GoASTEllipsis &) = delete;
+    const GoASTEllipsis &operator=(const GoASTEllipsis &) = delete;
+};
+
+class GoASTEmptyStmt : public GoASTStmt
+{
+  public:
+    GoASTEmptyStmt() : GoASTStmt(eEmptyStmt) {}
+    ~GoASTEmptyStmt() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "EmptyStmt";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eEmptyStmt;
+    }
+    
+    GoASTEmptyStmt(const GoASTEmptyStmt &) = delete;
+    const GoASTEmptyStmt &operator=(const GoASTEmptyStmt &) = delete;
+};
+
+class GoASTExprStmt : public GoASTStmt
+{
+  public:
+    explicit GoASTExprStmt(GoASTExpr *x) : GoASTStmt(eExprStmt), m_x_up(x) {}
+    ~GoASTExprStmt() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "ExprStmt";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eExprStmt;
+    }
+    
+    const GoASTExpr *
+    GetX() const
+    {
+        return m_x_up.get();
+    }
+    void
+    SetX(GoASTExpr *x)
+    {
+        m_x_up.reset(x);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTExpr> m_x_up;
+
+    GoASTExprStmt(const GoASTExprStmt &) = delete;
+    const GoASTExprStmt &operator=(const GoASTExprStmt &) = delete;
+};
+
+class GoASTField : public GoASTNode
+{
+  public:
+    GoASTField() : GoASTNode(eField) {}
+    ~GoASTField() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "Field";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eField;
+    }
+    
+    size_t
+    NumNames() const
+    {
+        return m_names.size();
+    }
+    const GoASTIdent *
+    GetNames(int i) const
+    {
+        return m_names[i].get();
+    }
+    void
+    AddNames(GoASTIdent *names)
+    {
+        m_names.push_back(std::unique_ptr<GoASTIdent>(names));
+    }
+
+    const GoASTExpr *
+    GetType() const
+    {
+        return m_type_up.get();
+    }
+    void
+    SetType(GoASTExpr *type)
+    {
+        m_type_up.reset(type);
+    }
+
+    const GoASTBasicLit *
+    GetTag() const
+    {
+        return m_tag_up.get();
+    }
+    void
+    SetTag(GoASTBasicLit *tag)
+    {
+        m_tag_up.reset(tag);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::vector<std::unique_ptr<GoASTIdent> > m_names;
+    std::unique_ptr<GoASTExpr> m_type_up;
+    std::unique_ptr<GoASTBasicLit> m_tag_up;
+
+    GoASTField(const GoASTField &) = delete;
+    const GoASTField &operator=(const GoASTField &) = delete;
+};
+
+class GoASTFieldList : public GoASTNode
+{
+  public:
+    GoASTFieldList() : GoASTNode(eFieldList) {}
+    ~GoASTFieldList() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "FieldList";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eFieldList;
+    }
+    
+    size_t
+    NumList() const
+    {
+        return m_list.size();
+    }
+    const GoASTField *
+    GetList(int i) const
+    {
+        return m_list[i].get();
+    }
+    void
+    AddList(GoASTField *list)
+    {
+        m_list.push_back(std::unique_ptr<GoASTField>(list));
+    }
+
+  private:
+    friend class GoASTNode;
+    std::vector<std::unique_ptr<GoASTField> > m_list;
+
+    GoASTFieldList(const GoASTFieldList &) = delete;
+    const GoASTFieldList &operator=(const GoASTFieldList &) = delete;
+};
+
+class GoASTForStmt : public GoASTStmt
+{
+  public:
+    GoASTForStmt(GoASTStmt *init, GoASTExpr *cond, GoASTStmt *post, GoASTBlockStmt *body) : GoASTStmt(eForStmt), m_init_up(init), m_cond_up(cond), m_post_up(post), m_body_up(body) {}
+    ~GoASTForStmt() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "ForStmt";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eForStmt;
+    }
+    
+    const GoASTStmt *
+    GetInit() const
+    {
+        return m_init_up.get();
+    }
+    void
+    SetInit(GoASTStmt *init)
+    {
+        m_init_up.reset(init);
+    }
+
+    const GoASTExpr *
+    GetCond() const
+    {
+        return m_cond_up.get();
+    }
+    void
+    SetCond(GoASTExpr *cond)
+    {
+        m_cond_up.reset(cond);
+    }
+
+    const GoASTStmt *
+    GetPost() const
+    {
+        return m_post_up.get();
+    }
+    void
+    SetPost(GoASTStmt *post)
+    {
+        m_post_up.reset(post);
+    }
+
+    const GoASTBlockStmt *
+    GetBody() const
+    {
+        return m_body_up.get();
+    }
+    void
+    SetBody(GoASTBlockStmt *body)
+    {
+        m_body_up.reset(body);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTStmt> m_init_up;
+    std::unique_ptr<GoASTExpr> m_cond_up;
+    std::unique_ptr<GoASTStmt> m_post_up;
+    std::unique_ptr<GoASTBlockStmt> m_body_up;
+
+    GoASTForStmt(const GoASTForStmt &) = delete;
+    const GoASTForStmt &operator=(const GoASTForStmt &) = delete;
+};
+
+class GoASTFuncType : public GoASTExpr
+{
+  public:
+    GoASTFuncType(GoASTFieldList *params, GoASTFieldList *results) : GoASTExpr(eFuncType), m_params_up(params), m_results_up(results) {}
+    ~GoASTFuncType() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "FuncType";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eFuncType;
+    }
+    
+    const GoASTFieldList *
+    GetParams() const
+    {
+        return m_params_up.get();
+    }
+    void
+    SetParams(GoASTFieldList *params)
+    {
+        m_params_up.reset(params);
+    }
+
+    const GoASTFieldList *
+    GetResults() const
+    {
+        return m_results_up.get();
+    }
+    void
+    SetResults(GoASTFieldList *results)
+    {
+        m_results_up.reset(results);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTFieldList> m_params_up;
+    std::unique_ptr<GoASTFieldList> m_results_up;
+
+    GoASTFuncType(const GoASTFuncType &) = delete;
+    const GoASTFuncType &operator=(const GoASTFuncType &) = delete;
+};
+
+class GoASTFuncDecl : public GoASTDecl
+{
+  public:
+    GoASTFuncDecl(GoASTFieldList *recv, GoASTIdent *name, GoASTFuncType *type, GoASTBlockStmt *body) : GoASTDecl(eFuncDecl), m_recv_up(recv), m_name_up(name), m_type_up(type), m_body_up(body) {}
+    ~GoASTFuncDecl() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "FuncDecl";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eFuncDecl;
+    }
+    
+    const GoASTFieldList *
+    GetRecv() const
+    {
+        return m_recv_up.get();
+    }
+    void
+    SetRecv(GoASTFieldList *recv)
+    {
+        m_recv_up.reset(recv);
+    }
+
+    const GoASTIdent *
+    GetName() const
+    {
+        return m_name_up.get();
+    }
+    void
+    SetName(GoASTIdent *name)
+    {
+        m_name_up.reset(name);
+    }
+
+    const GoASTFuncType *
+    GetType() const
+    {
+        return m_type_up.get();
+    }
+    void
+    SetType(GoASTFuncType *type)
+    {
+        m_type_up.reset(type);
+    }
+
+    const GoASTBlockStmt *
+    GetBody() const
+    {
+        return m_body_up.get();
+    }
+    void
+    SetBody(GoASTBlockStmt *body)
+    {
+        m_body_up.reset(body);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTFieldList> m_recv_up;
+    std::unique_ptr<GoASTIdent> m_name_up;
+    std::unique_ptr<GoASTFuncType> m_type_up;
+    std::unique_ptr<GoASTBlockStmt> m_body_up;
+
+    GoASTFuncDecl(const GoASTFuncDecl &) = delete;
+    const GoASTFuncDecl &operator=(const GoASTFuncDecl &) = delete;
+};
+
+class GoASTFuncLit : public GoASTExpr
+{
+  public:
+    GoASTFuncLit(GoASTFuncType *type, GoASTBlockStmt *body) : GoASTExpr(eFuncLit), m_type_up(type), m_body_up(body) {}
+    ~GoASTFuncLit() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "FuncLit";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eFuncLit;
+    }
+    
+    const GoASTFuncType *
+    GetType() const
+    {
+        return m_type_up.get();
+    }
+    void
+    SetType(GoASTFuncType *type)
+    {
+        m_type_up.reset(type);
+    }
+
+    const GoASTBlockStmt *
+    GetBody() const
+    {
+        return m_body_up.get();
+    }
+    void
+    SetBody(GoASTBlockStmt *body)
+    {
+        m_body_up.reset(body);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTFuncType> m_type_up;
+    std::unique_ptr<GoASTBlockStmt> m_body_up;
+
+    GoASTFuncLit(const GoASTFuncLit &) = delete;
+    const GoASTFuncLit &operator=(const GoASTFuncLit &) = delete;
+};
+
+class GoASTGenDecl : public GoASTDecl
+{
+  public:
+    explicit GoASTGenDecl(TokenType tok) : GoASTDecl(eGenDecl), m_tok(tok) {}
+    ~GoASTGenDecl() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "GenDecl";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eGenDecl;
+    }
+    
+    TokenType 
+    GetTok() const
+    {
+        return m_tok;
+    }
+    void
+    SetTok(TokenType tok)
+    {
+        m_tok = tok;
+    }
+
+    size_t
+    NumSpecs() const
+    {
+        return m_specs.size();
+    }
+    const GoASTSpec *
+    GetSpecs(int i) const
+    {
+        return m_specs[i].get();
+    }
+    void
+    AddSpecs(GoASTSpec *specs)
+    {
+        m_specs.push_back(std::unique_ptr<GoASTSpec>(specs));
+    }
+
+  private:
+    friend class GoASTNode;
+    TokenType m_tok;
+    std::vector<std::unique_ptr<GoASTSpec> > m_specs;
+
+    GoASTGenDecl(const GoASTGenDecl &) = delete;
+    const GoASTGenDecl &operator=(const GoASTGenDecl &) = delete;
+};
+
+class GoASTGoStmt : public GoASTStmt
+{
+  public:
+    explicit GoASTGoStmt(GoASTCallExpr *call) : GoASTStmt(eGoStmt), m_call_up(call) {}
+    ~GoASTGoStmt() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "GoStmt";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eGoStmt;
+    }
+    
+    const GoASTCallExpr *
+    GetCall() const
+    {
+        return m_call_up.get();
+    }
+    void
+    SetCall(GoASTCallExpr *call)
+    {
+        m_call_up.reset(call);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTCallExpr> m_call_up;
+
+    GoASTGoStmt(const GoASTGoStmt &) = delete;
+    const GoASTGoStmt &operator=(const GoASTGoStmt &) = delete;
+};
+
+class GoASTIfStmt : public GoASTStmt
+{
+  public:
+    GoASTIfStmt(GoASTStmt *init, GoASTExpr *cond, GoASTBlockStmt *body, GoASTStmt *els) : GoASTStmt(eIfStmt), m_init_up(init), m_cond_up(cond), m_body_up(body), m_els_up(els) {}
+    ~GoASTIfStmt() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "IfStmt";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eIfStmt;
+    }
+    
+    const GoASTStmt *
+    GetInit() const
+    {
+        return m_init_up.get();
+    }
+    void
+    SetInit(GoASTStmt *init)
+    {
+        m_init_up.reset(init);
+    }
+
+    const GoASTExpr *
+    GetCond() const
+    {
+        return m_cond_up.get();
+    }
+    void
+    SetCond(GoASTExpr *cond)
+    {
+        m_cond_up.reset(cond);
+    }
+
+    const GoASTBlockStmt *
+    GetBody() const
+    {
+        return m_body_up.get();
+    }
+    void
+    SetBody(GoASTBlockStmt *body)
+    {
+        m_body_up.reset(body);
+    }
+
+    const GoASTStmt *
+    GetEls() const
+    {
+        return m_els_up.get();
+    }
+    void
+    SetEls(GoASTStmt *els)
+    {
+        m_els_up.reset(els);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTStmt> m_init_up;
+    std::unique_ptr<GoASTExpr> m_cond_up;
+    std::unique_ptr<GoASTBlockStmt> m_body_up;
+    std::unique_ptr<GoASTStmt> m_els_up;
+
+    GoASTIfStmt(const GoASTIfStmt &) = delete;
+    const GoASTIfStmt &operator=(const GoASTIfStmt &) = delete;
+};
+
+class GoASTImportSpec : public GoASTSpec
+{
+  public:
+    GoASTImportSpec(GoASTIdent *name, GoASTBasicLit *path) : GoASTSpec(eImportSpec), m_name_up(name), m_path_up(path) {}
+    ~GoASTImportSpec() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "ImportSpec";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eImportSpec;
+    }
+    
+    const GoASTIdent *
+    GetName() const
+    {
+        return m_name_up.get();
+    }
+    void
+    SetName(GoASTIdent *name)
+    {
+        m_name_up.reset(name);
+    }
+
+    const GoASTBasicLit *
+    GetPath() const
+    {
+        return m_path_up.get();
+    }
+    void
+    SetPath(GoASTBasicLit *path)
+    {
+        m_path_up.reset(path);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTIdent> m_name_up;
+    std::unique_ptr<GoASTBasicLit> m_path_up;
+
+    GoASTImportSpec(const GoASTImportSpec &) = delete;
+    const GoASTImportSpec &operator=(const GoASTImportSpec &) = delete;
+};
+
+class GoASTIncDecStmt : public GoASTStmt
+{
+  public:
+    GoASTIncDecStmt(GoASTExpr *x, TokenType tok) : GoASTStmt(eIncDecStmt), m_x_up(x), m_tok(tok) {}
+    ~GoASTIncDecStmt() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "IncDecStmt";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eIncDecStmt;
+    }
+    
+    const GoASTExpr *
+    GetX() const
+    {
+        return m_x_up.get();
+    }
+    void
+    SetX(GoASTExpr *x)
+    {
+        m_x_up.reset(x);
+    }
+
+    TokenType 
+    GetTok() const
+    {
+        return m_tok;
+    }
+    void
+    SetTok(TokenType tok)
+    {
+        m_tok = tok;
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTExpr> m_x_up;
+    TokenType m_tok;
+
+    GoASTIncDecStmt(const GoASTIncDecStmt &) = delete;
+    const GoASTIncDecStmt &operator=(const GoASTIncDecStmt &) = delete;
+};
+
+class GoASTIndexExpr : public GoASTExpr
+{
+  public:
+    GoASTIndexExpr(GoASTExpr *x, GoASTExpr *index) : GoASTExpr(eIndexExpr), m_x_up(x), m_index_up(index) {}
+    ~GoASTIndexExpr() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "IndexExpr";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eIndexExpr;
+    }
+    
+    const GoASTExpr *
+    GetX() const
+    {
+        return m_x_up.get();
+    }
+    void
+    SetX(GoASTExpr *x)
+    {
+        m_x_up.reset(x);
+    }
+
+    const GoASTExpr *
+    GetIndex() const
+    {
+        return m_index_up.get();
+    }
+    void
+    SetIndex(GoASTExpr *index)
+    {
+        m_index_up.reset(index);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTExpr> m_x_up;
+    std::unique_ptr<GoASTExpr> m_index_up;
+
+    GoASTIndexExpr(const GoASTIndexExpr &) = delete;
+    const GoASTIndexExpr &operator=(const GoASTIndexExpr &) = delete;
+};
+
+class GoASTInterfaceType : public GoASTExpr
+{
+  public:
+    explicit GoASTInterfaceType(GoASTFieldList *methods) : GoASTExpr(eInterfaceType), m_methods_up(methods) {}
+    ~GoASTInterfaceType() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "InterfaceType";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eInterfaceType;
+    }
+    
+    const GoASTFieldList *
+    GetMethods() const
+    {
+        return m_methods_up.get();
+    }
+    void
+    SetMethods(GoASTFieldList *methods)
+    {
+        m_methods_up.reset(methods);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTFieldList> m_methods_up;
+
+    GoASTInterfaceType(const GoASTInterfaceType &) = delete;
+    const GoASTInterfaceType &operator=(const GoASTInterfaceType &) = delete;
+};
+
+class GoASTKeyValueExpr : public GoASTExpr
+{
+  public:
+    GoASTKeyValueExpr(GoASTExpr *key, GoASTExpr *value) : GoASTExpr(eKeyValueExpr), m_key_up(key), m_value_up(value) {}
+    ~GoASTKeyValueExpr() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "KeyValueExpr";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eKeyValueExpr;
+    }
+    
+    const GoASTExpr *
+    GetKey() const
+    {
+        return m_key_up.get();
+    }
+    void
+    SetKey(GoASTExpr *key)
+    {
+        m_key_up.reset(key);
+    }
+
+    const GoASTExpr *
+    GetValue() const
+    {
+        return m_value_up.get();
+    }
+    void
+    SetValue(GoASTExpr *value)
+    {
+        m_value_up.reset(value);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTExpr> m_key_up;
+    std::unique_ptr<GoASTExpr> m_value_up;
+
+    GoASTKeyValueExpr(const GoASTKeyValueExpr &) = delete;
+    const GoASTKeyValueExpr &operator=(const GoASTKeyValueExpr &) = delete;
+};
+
+class GoASTLabeledStmt : public GoASTStmt
+{
+  public:
+    GoASTLabeledStmt(GoASTIdent *label, GoASTStmt *stmt) : GoASTStmt(eLabeledStmt), m_label_up(label), m_stmt_up(stmt) {}
+    ~GoASTLabeledStmt() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "LabeledStmt";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eLabeledStmt;
+    }
+    
+    const GoASTIdent *
+    GetLabel() const
+    {
+        return m_label_up.get();
+    }
+    void
+    SetLabel(GoASTIdent *label)
+    {
+        m_label_up.reset(label);
+    }
+
+    const GoASTStmt *
+    GetStmt() const
+    {
+        return m_stmt_up.get();
+    }
+    void
+    SetStmt(GoASTStmt *stmt)
+    {
+        m_stmt_up.reset(stmt);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTIdent> m_label_up;
+    std::unique_ptr<GoASTStmt> m_stmt_up;
+
+    GoASTLabeledStmt(const GoASTLabeledStmt &) = delete;
+    const GoASTLabeledStmt &operator=(const GoASTLabeledStmt &) = delete;
+};
+
+class GoASTMapType : public GoASTExpr
+{
+  public:
+    GoASTMapType(GoASTExpr *key, GoASTExpr *value) : GoASTExpr(eMapType), m_key_up(key), m_value_up(value) {}
+    ~GoASTMapType() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "MapType";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eMapType;
+    }
+    
+    const GoASTExpr *
+    GetKey() const
+    {
+        return m_key_up.get();
+    }
+    void
+    SetKey(GoASTExpr *key)
+    {
+        m_key_up.reset(key);
+    }
+
+    const GoASTExpr *
+    GetValue() const
+    {
+        return m_value_up.get();
+    }
+    void
+    SetValue(GoASTExpr *value)
+    {
+        m_value_up.reset(value);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTExpr> m_key_up;
+    std::unique_ptr<GoASTExpr> m_value_up;
+
+    GoASTMapType(const GoASTMapType &) = delete;
+    const GoASTMapType &operator=(const GoASTMapType &) = delete;
+};
+
+class GoASTParenExpr : public GoASTExpr
+{
+  public:
+    explicit GoASTParenExpr(GoASTExpr *x) : GoASTExpr(eParenExpr), m_x_up(x) {}
+    ~GoASTParenExpr() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "ParenExpr";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eParenExpr;
+    }
+    
+    const GoASTExpr *
+    GetX() const
+    {
+        return m_x_up.get();
+    }
+    void
+    SetX(GoASTExpr *x)
+    {
+        m_x_up.reset(x);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTExpr> m_x_up;
+
+    GoASTParenExpr(const GoASTParenExpr &) = delete;
+    const GoASTParenExpr &operator=(const GoASTParenExpr &) = delete;
+};
+
+class GoASTRangeStmt : public GoASTStmt
+{
+  public:
+    GoASTRangeStmt(GoASTExpr *key, GoASTExpr *value, bool define, GoASTExpr *x, GoASTBlockStmt *body) : GoASTStmt(eRangeStmt), m_key_up(key), m_value_up(value), m_define(define), m_x_up(x), m_body_up(body) {}
+    ~GoASTRangeStmt() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "RangeStmt";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eRangeStmt;
+    }
+    
+    const GoASTExpr *
+    GetKey() const
+    {
+        return m_key_up.get();
+    }
+    void
+    SetKey(GoASTExpr *key)
+    {
+        m_key_up.reset(key);
+    }
+
+    const GoASTExpr *
+    GetValue() const
+    {
+        return m_value_up.get();
+    }
+    void
+    SetValue(GoASTExpr *value)
+    {
+        m_value_up.reset(value);
+    }
+
+    bool 
+    GetDefine() const
+    {
+        return m_define;
+    }
+    void
+    SetDefine(bool define)
+    {
+        m_define = define;
+    }
+
+    const GoASTExpr *
+    GetX() const
+    {
+        return m_x_up.get();
+    }
+    void
+    SetX(GoASTExpr *x)
+    {
+        m_x_up.reset(x);
+    }
+
+    const GoASTBlockStmt *
+    GetBody() const
+    {
+        return m_body_up.get();
+    }
+    void
+    SetBody(GoASTBlockStmt *body)
+    {
+        m_body_up.reset(body);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTExpr> m_key_up;
+    std::unique_ptr<GoASTExpr> m_value_up;
+    bool m_define;
+    std::unique_ptr<GoASTExpr> m_x_up;
+    std::unique_ptr<GoASTBlockStmt> m_body_up;
+
+    GoASTRangeStmt(const GoASTRangeStmt &) = delete;
+    const GoASTRangeStmt &operator=(const GoASTRangeStmt &) = delete;
+};
+
+class GoASTReturnStmt : public GoASTStmt
+{
+  public:
+    GoASTReturnStmt() : GoASTStmt(eReturnStmt) {}
+    ~GoASTReturnStmt() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "ReturnStmt";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eReturnStmt;
+    }
+    
+    size_t
+    NumResults() const
+    {
+        return m_results.size();
+    }
+    const GoASTExpr *
+    GetResults(int i) const
+    {
+        return m_results[i].get();
+    }
+    void
+    AddResults(GoASTExpr *results)
+    {
+        m_results.push_back(std::unique_ptr<GoASTExpr>(results));
+    }
+
+  private:
+    friend class GoASTNode;
+    std::vector<std::unique_ptr<GoASTExpr> > m_results;
+
+    GoASTReturnStmt(const GoASTReturnStmt &) = delete;
+    const GoASTReturnStmt &operator=(const GoASTReturnStmt &) = delete;
+};
+
+class GoASTSelectStmt : public GoASTStmt
+{
+  public:
+    explicit GoASTSelectStmt(GoASTBlockStmt *body) : GoASTStmt(eSelectStmt), m_body_up(body) {}
+    ~GoASTSelectStmt() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "SelectStmt";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eSelectStmt;
+    }
+    
+    const GoASTBlockStmt *
+    GetBody() const
+    {
+        return m_body_up.get();
+    }
+    void
+    SetBody(GoASTBlockStmt *body)
+    {
+        m_body_up.reset(body);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTBlockStmt> m_body_up;
+
+    GoASTSelectStmt(const GoASTSelectStmt &) = delete;
+    const GoASTSelectStmt &operator=(const GoASTSelectStmt &) = delete;
+};
+
+class GoASTSelectorExpr : public GoASTExpr
+{
+  public:
+    GoASTSelectorExpr(GoASTExpr *x, GoASTIdent *sel) : GoASTExpr(eSelectorExpr), m_x_up(x), m_sel_up(sel) {}
+    ~GoASTSelectorExpr() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "SelectorExpr";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eSelectorExpr;
+    }
+    
+    const GoASTExpr *
+    GetX() const
+    {
+        return m_x_up.get();
+    }
+    void
+    SetX(GoASTExpr *x)
+    {
+        m_x_up.reset(x);
+    }
+
+    const GoASTIdent *
+    GetSel() const
+    {
+        return m_sel_up.get();
+    }
+    void
+    SetSel(GoASTIdent *sel)
+    {
+        m_sel_up.reset(sel);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTExpr> m_x_up;
+    std::unique_ptr<GoASTIdent> m_sel_up;
+
+    GoASTSelectorExpr(const GoASTSelectorExpr &) = delete;
+    const GoASTSelectorExpr &operator=(const GoASTSelectorExpr &) = delete;
+};
+
+class GoASTSendStmt : public GoASTStmt
+{
+  public:
+    GoASTSendStmt(GoASTExpr *chan, GoASTExpr *value) : GoASTStmt(eSendStmt), m_chan_up(chan), m_value_up(value) {}
+    ~GoASTSendStmt() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "SendStmt";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eSendStmt;
+    }
+    
+    const GoASTExpr *
+    GetChan() const
+    {
+        return m_chan_up.get();
+    }
+    void
+    SetChan(GoASTExpr *chan)
+    {
+        m_chan_up.reset(chan);
+    }
+
+    const GoASTExpr *
+    GetValue() const
+    {
+        return m_value_up.get();
+    }
+    void
+    SetValue(GoASTExpr *value)
+    {
+        m_value_up.reset(value);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTExpr> m_chan_up;
+    std::unique_ptr<GoASTExpr> m_value_up;
+
+    GoASTSendStmt(const GoASTSendStmt &) = delete;
+    const GoASTSendStmt &operator=(const GoASTSendStmt &) = delete;
+};
+
+class GoASTSliceExpr : public GoASTExpr
+{
+  public:
+    GoASTSliceExpr(GoASTExpr *x, GoASTExpr *low, GoASTExpr *high, GoASTExpr *max, bool slice3) : GoASTExpr(eSliceExpr), m_x_up(x), m_low_up(low), m_high_up(high), m_max_up(max), m_slice3(slice3) {}
+    ~GoASTSliceExpr() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "SliceExpr";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eSliceExpr;
+    }
+    
+    const GoASTExpr *
+    GetX() const
+    {
+        return m_x_up.get();
+    }
+    void
+    SetX(GoASTExpr *x)
+    {
+        m_x_up.reset(x);
+    }
+
+    const GoASTExpr *
+    GetLow() const
+    {
+        return m_low_up.get();
+    }
+    void
+    SetLow(GoASTExpr *low)
+    {
+        m_low_up.reset(low);
+    }
+
+    const GoASTExpr *
+    GetHigh() const
+    {
+        return m_high_up.get();
+    }
+    void
+    SetHigh(GoASTExpr *high)
+    {
+        m_high_up.reset(high);
+    }
+
+    const GoASTExpr *
+    GetMax() const
+    {
+        return m_max_up.get();
+    }
+    void
+    SetMax(GoASTExpr *max)
+    {
+        m_max_up.reset(max);
+    }
+
+    bool 
+    GetSlice3() const
+    {
+        return m_slice3;
+    }
+    void
+    SetSlice3(bool slice3)
+    {
+        m_slice3 = slice3;
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTExpr> m_x_up;
+    std::unique_ptr<GoASTExpr> m_low_up;
+    std::unique_ptr<GoASTExpr> m_high_up;
+    std::unique_ptr<GoASTExpr> m_max_up;
+    bool m_slice3;
+
+    GoASTSliceExpr(const GoASTSliceExpr &) = delete;
+    const GoASTSliceExpr &operator=(const GoASTSliceExpr &) = delete;
+};
+
+class GoASTStarExpr : public GoASTExpr
+{
+  public:
+    explicit GoASTStarExpr(GoASTExpr *x) : GoASTExpr(eStarExpr), m_x_up(x) {}
+    ~GoASTStarExpr() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "StarExpr";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eStarExpr;
+    }
+    
+    const GoASTExpr *
+    GetX() const
+    {
+        return m_x_up.get();
+    }
+    void
+    SetX(GoASTExpr *x)
+    {
+        m_x_up.reset(x);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTExpr> m_x_up;
+
+    GoASTStarExpr(const GoASTStarExpr &) = delete;
+    const GoASTStarExpr &operator=(const GoASTStarExpr &) = delete;
+};
+
+class GoASTStructType : public GoASTExpr
+{
+  public:
+    explicit GoASTStructType(GoASTFieldList *fields) : GoASTExpr(eStructType), m_fields_up(fields) {}
+    ~GoASTStructType() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "StructType";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eStructType;
+    }
+    
+    const GoASTFieldList *
+    GetFields() const
+    {
+        return m_fields_up.get();
+    }
+    void
+    SetFields(GoASTFieldList *fields)
+    {
+        m_fields_up.reset(fields);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTFieldList> m_fields_up;
+
+    GoASTStructType(const GoASTStructType &) = delete;
+    const GoASTStructType &operator=(const GoASTStructType &) = delete;
+};
+
+class GoASTSwitchStmt : public GoASTStmt
+{
+  public:
+    GoASTSwitchStmt(GoASTStmt *init, GoASTExpr *tag, GoASTBlockStmt *body) : GoASTStmt(eSwitchStmt), m_init_up(init), m_tag_up(tag), m_body_up(body) {}
+    ~GoASTSwitchStmt() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "SwitchStmt";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eSwitchStmt;
+    }
+    
+    const GoASTStmt *
+    GetInit() const
+    {
+        return m_init_up.get();
+    }
+    void
+    SetInit(GoASTStmt *init)
+    {
+        m_init_up.reset(init);
+    }
+
+    const GoASTExpr *
+    GetTag() const
+    {
+        return m_tag_up.get();
+    }
+    void
+    SetTag(GoASTExpr *tag)
+    {
+        m_tag_up.reset(tag);
+    }
+
+    const GoASTBlockStmt *
+    GetBody() const
+    {
+        return m_body_up.get();
+    }
+    void
+    SetBody(GoASTBlockStmt *body)
+    {
+        m_body_up.reset(body);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTStmt> m_init_up;
+    std::unique_ptr<GoASTExpr> m_tag_up;
+    std::unique_ptr<GoASTBlockStmt> m_body_up;
+
+    GoASTSwitchStmt(const GoASTSwitchStmt &) = delete;
+    const GoASTSwitchStmt &operator=(const GoASTSwitchStmt &) = delete;
+};
+
+class GoASTTypeAssertExpr : public GoASTExpr
+{
+  public:
+    GoASTTypeAssertExpr(GoASTExpr *x, GoASTExpr *type) : GoASTExpr(eTypeAssertExpr), m_x_up(x), m_type_up(type) {}
+    ~GoASTTypeAssertExpr() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "TypeAssertExpr";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eTypeAssertExpr;
+    }
+    
+    const GoASTExpr *
+    GetX() const
+    {
+        return m_x_up.get();
+    }
+    void
+    SetX(GoASTExpr *x)
+    {
+        m_x_up.reset(x);
+    }
+
+    const GoASTExpr *
+    GetType() const
+    {
+        return m_type_up.get();
+    }
+    void
+    SetType(GoASTExpr *type)
+    {
+        m_type_up.reset(type);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTExpr> m_x_up;
+    std::unique_ptr<GoASTExpr> m_type_up;
+
+    GoASTTypeAssertExpr(const GoASTTypeAssertExpr &) = delete;
+    const GoASTTypeAssertExpr &operator=(const GoASTTypeAssertExpr &) = delete;
+};
+
+class GoASTTypeSpec : public GoASTSpec
+{
+  public:
+    GoASTTypeSpec(GoASTIdent *name, GoASTExpr *type) : GoASTSpec(eTypeSpec), m_name_up(name), m_type_up(type) {}
+    ~GoASTTypeSpec() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "TypeSpec";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eTypeSpec;
+    }
+    
+    const GoASTIdent *
+    GetName() const
+    {
+        return m_name_up.get();
+    }
+    void
+    SetName(GoASTIdent *name)
+    {
+        m_name_up.reset(name);
+    }
+
+    const GoASTExpr *
+    GetType() const
+    {
+        return m_type_up.get();
+    }
+    void
+    SetType(GoASTExpr *type)
+    {
+        m_type_up.reset(type);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTIdent> m_name_up;
+    std::unique_ptr<GoASTExpr> m_type_up;
+
+    GoASTTypeSpec(const GoASTTypeSpec &) = delete;
+    const GoASTTypeSpec &operator=(const GoASTTypeSpec &) = delete;
+};
+
+class GoASTTypeSwitchStmt : public GoASTStmt
+{
+  public:
+    GoASTTypeSwitchStmt(GoASTStmt *init, GoASTStmt *assign, GoASTBlockStmt *body) : GoASTStmt(eTypeSwitchStmt), m_init_up(init), m_assign_up(assign), m_body_up(body) {}
+    ~GoASTTypeSwitchStmt() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "TypeSwitchStmt";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eTypeSwitchStmt;
+    }
+    
+    const GoASTStmt *
+    GetInit() const
+    {
+        return m_init_up.get();
+    }
+    void
+    SetInit(GoASTStmt *init)
+    {
+        m_init_up.reset(init);
+    }
+
+    const GoASTStmt *
+    GetAssign() const
+    {
+        return m_assign_up.get();
+    }
+    void
+    SetAssign(GoASTStmt *assign)
+    {
+        m_assign_up.reset(assign);
+    }
+
+    const GoASTBlockStmt *
+    GetBody() const
+    {
+        return m_body_up.get();
+    }
+    void
+    SetBody(GoASTBlockStmt *body)
+    {
+        m_body_up.reset(body);
+    }
+
+  private:
+    friend class GoASTNode;
+    std::unique_ptr<GoASTStmt> m_init_up;
+    std::unique_ptr<GoASTStmt> m_assign_up;
+    std::unique_ptr<GoASTBlockStmt> m_body_up;
+
+    GoASTTypeSwitchStmt(const GoASTTypeSwitchStmt &) = delete;
+    const GoASTTypeSwitchStmt &operator=(const GoASTTypeSwitchStmt &) = delete;
+};
+
+class GoASTUnaryExpr : public GoASTExpr
+{
+  public:
+    GoASTUnaryExpr(TokenType op, GoASTExpr *x) : GoASTExpr(eUnaryExpr), m_op(op), m_x_up(x) {}
+    ~GoASTUnaryExpr() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "UnaryExpr";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eUnaryExpr;
+    }
+    
+    TokenType 
+    GetOp() const
+    {
+        return m_op;
+    }
+    void
+    SetOp(TokenType op)
+    {
+        m_op = op;
+    }
+
+    const GoASTExpr *
+    GetX() const
+    {
+        return m_x_up.get();
+    }
+    void
+    SetX(GoASTExpr *x)
+    {
+        m_x_up.reset(x);
+    }
+
+  private:
+    friend class GoASTNode;
+    TokenType m_op;
+    std::unique_ptr<GoASTExpr> m_x_up;
+
+    GoASTUnaryExpr(const GoASTUnaryExpr &) = delete;
+    const GoASTUnaryExpr &operator=(const GoASTUnaryExpr &) = delete;
+};
+
+class GoASTValueSpec : public GoASTSpec
+{
+  public:
+    GoASTValueSpec() : GoASTSpec(eValueSpec) {}
+    ~GoASTValueSpec() override = default;
+
+    const char *
+    GetKindName() const override
+    {
+        return "ValueSpec";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == eValueSpec;
+    }
+    
+    size_t
+    NumNames() const
+    {
+        return m_names.size();
+    }
+    const GoASTIdent *
+    GetNames(int i) const
+    {
+        return m_names[i].get();
+    }
+    void
+    AddNames(GoASTIdent *names)
+    {
+        m_names.push_back(std::unique_ptr<GoASTIdent>(names));
+    }
+
+    const GoASTExpr *
+    GetType() const
+    {
+        return m_type_up.get();
+    }
+    void
+    SetType(GoASTExpr *type)
+    {
+        m_type_up.reset(type);
+    }
+
+    size_t
+    NumValues() const
+    {
+        return m_values.size();
+    }
+    const GoASTExpr *
+    GetValues(int i) const
+    {
+        return m_values[i].get();
+    }
+    void
+    AddValues(GoASTExpr *values)
+    {
+        m_values.push_back(std::unique_ptr<GoASTExpr>(values));
+    }
+
+  private:
+    friend class GoASTNode;
+    std::vector<std::unique_ptr<GoASTIdent> > m_names;
+    std::unique_ptr<GoASTExpr> m_type_up;
+    std::vector<std::unique_ptr<GoASTExpr> > m_values;
+
+    GoASTValueSpec(const GoASTValueSpec &) = delete;
+    const GoASTValueSpec &operator=(const GoASTValueSpec &) = delete;
+};
+
+
+template <typename R, typename V>
+R GoASTDecl::Visit(V* v) const
+{
+    switch(GetKind())
+    {
+    case eBadDecl:
+        return v->VisitBadDecl(llvm::cast<const GoASTBadDecl>(this));
+    case eFuncDecl:
+        return v->VisitFuncDecl(llvm::cast<const GoASTFuncDecl>(this));
+    case eGenDecl:
+        return v->VisitGenDecl(llvm::cast<const GoASTGenDecl>(this));
+    default:
+        assert(false && "Invalid kind");
+    }
+}
+
+template <typename R, typename V>
+R GoASTExpr::Visit(V* v) const
+{
+    switch(GetKind())
+    {
+    case eArrayType:
+        return v->VisitArrayType(llvm::cast<const GoASTArrayType>(this));
+    case eBadExpr:
+        return v->VisitBadExpr(llvm::cast<const GoASTBadExpr>(this));
+    case eBasicLit:
+        return v->VisitBasicLit(llvm::cast<const GoASTBasicLit>(this));
+    case eBinaryExpr:
+        return v->VisitBinaryExpr(llvm::cast<const GoASTBinaryExpr>(this));
+    case eIdent:
+        return v->VisitIdent(llvm::cast<const GoASTIdent>(this));
+    case eCallExpr:
+        return v->VisitCallExpr(llvm::cast<const GoASTCallExpr>(this));
+    case eChanType:
+        return v->VisitChanType(llvm::cast<const GoASTChanType>(this));
+    case eCompositeLit:
+        return v->VisitCompositeLit(llvm::cast<const GoASTCompositeLit>(this));
+    case eEllipsis:
+        return v->VisitEllipsis(llvm::cast<const GoASTEllipsis>(this));
+    case eFuncType:
+        return v->VisitFuncType(llvm::cast<const GoASTFuncType>(this));
+    case eFuncLit:
+        return v->VisitFuncLit(llvm::cast<const GoASTFuncLit>(this));
+    case eIndexExpr:
+        return v->VisitIndexExpr(llvm::cast<const GoASTIndexExpr>(this));
+    case eInterfaceType:
+        return v->VisitInterfaceType(llvm::cast<const GoASTInterfaceType>(this));
+    case eKeyValueExpr:
+        return v->VisitKeyValueExpr(llvm::cast<const GoASTKeyValueExpr>(this));
+    case eMapType:
+        return v->VisitMapType(llvm::cast<const GoASTMapType>(this));
+    case eParenExpr:
+        return v->VisitParenExpr(llvm::cast<const GoASTParenExpr>(this));
+    case eSelectorExpr:
+        return v->VisitSelectorExpr(llvm::cast<const GoASTSelectorExpr>(this));
+    case eSliceExpr:
+        return v->VisitSliceExpr(llvm::cast<const GoASTSliceExpr>(this));
+    case eStarExpr:
+        return v->VisitStarExpr(llvm::cast<const GoASTStarExpr>(this));
+    case eStructType:
+        return v->VisitStructType(llvm::cast<const GoASTStructType>(this));
+    case eTypeAssertExpr:
+        return v->VisitTypeAssertExpr(llvm::cast<const GoASTTypeAssertExpr>(this));
+    case eUnaryExpr:
+        return v->VisitUnaryExpr(llvm::cast<const GoASTUnaryExpr>(this));
+    default:
+        assert(false && "Invalid kind");
+    }
+}
+
+template <typename R, typename V>
+R GoASTSpec::Visit(V* v) const
+{
+    switch(GetKind())
+    {
+    case eImportSpec:
+        return v->VisitImportSpec(llvm::cast<const GoASTImportSpec>(this));
+    case eTypeSpec:
+        return v->VisitTypeSpec(llvm::cast<const GoASTTypeSpec>(this));
+    case eValueSpec:
+        return v->VisitValueSpec(llvm::cast<const GoASTValueSpec>(this));
+    default:
+        assert(false && "Invalid kind");
+    }
+}
+
+template <typename R, typename V>
+R GoASTStmt::Visit(V* v) const
+{
+    switch(GetKind())
+    {
+    case eAssignStmt:
+        return v->VisitAssignStmt(llvm::cast<const GoASTAssignStmt>(this));
+    case eBadStmt:
+        return v->VisitBadStmt(llvm::cast<const GoASTBadStmt>(this));
+    case eBlockStmt:
+        return v->VisitBlockStmt(llvm::cast<const GoASTBlockStmt>(this));
+    case eBranchStmt:
+        return v->VisitBranchStmt(llvm::cast<const GoASTBranchStmt>(this));
+    case eCaseClause:
+        return v->VisitCaseClause(llvm::cast<const GoASTCaseClause>(this));
+    case eCommClause:
+        return v->VisitCommClause(llvm::cast<const GoASTCommClause>(this));
+    case eDeclStmt:
+        return v->VisitDeclStmt(llvm::cast<const GoASTDeclStmt>(this));
+    case eDeferStmt:
+        return v->VisitDeferStmt(llvm::cast<const GoASTDeferStmt>(this));
+    case eEmptyStmt:
+        return v->VisitEmptyStmt(llvm::cast<const GoASTEmptyStmt>(this));
+    case eExprStmt:
+        return v->VisitExprStmt(llvm::cast<const GoASTExprStmt>(this));
+    case eForStmt:
+        return v->VisitForStmt(llvm::cast<const GoASTForStmt>(this));
+    case eGoStmt:
+        return v->VisitGoStmt(llvm::cast<const GoASTGoStmt>(this));
+    case eIfStmt:
+        return v->VisitIfStmt(llvm::cast<const GoASTIfStmt>(this));
+    case eIncDecStmt:
+        return v->VisitIncDecStmt(llvm::cast<const GoASTIncDecStmt>(this));
+    case eLabeledStmt:
+        return v->VisitLabeledStmt(llvm::cast<const GoASTLabeledStmt>(this));
+    case eRangeStmt:
+        return v->VisitRangeStmt(llvm::cast<const GoASTRangeStmt>(this));
+    case eReturnStmt:
+        return v->VisitReturnStmt(llvm::cast<const GoASTReturnStmt>(this));
+    case eSelectStmt:
+        return v->VisitSelectStmt(llvm::cast<const GoASTSelectStmt>(this));
+    case eSendStmt:
+        return v->VisitSendStmt(llvm::cast<const GoASTSendStmt>(this));
+    case eSwitchStmt:
+        return v->VisitSwitchStmt(llvm::cast<const GoASTSwitchStmt>(this));
+    case eTypeSwitchStmt:
+        return v->VisitTypeSwitchStmt(llvm::cast<const GoASTTypeSwitchStmt>(this));
+    default:
+        assert(false && "Invalid kind");
+    }
+}
+
+template <typename V>
+void GoASTNode::WalkChildren(V &v)
+{
+    switch (m_kind)
+    {
+
+
+    case eArrayType:
+        {
+            GoASTArrayType *n = llvm::cast<GoASTArrayType>(this);
+            (void)n;
+            v(n->m_len_up.get());
+            v(n->m_elt_up.get());
+            return;
+        }
+    case eAssignStmt:
+        {
+            GoASTAssignStmt *n = llvm::cast<GoASTAssignStmt>(this);
+            (void)n;
+            for (auto& e : n->m_lhs) { v(e.get()); }
+            for (auto& e : n->m_rhs) { v(e.get()); }
+            return;
+        }
+    case eBasicLit:
+        {
+            GoASTBasicLit *n = llvm::cast<GoASTBasicLit>(this);
+            (void)n;
+            return;
+        }
+    case eBinaryExpr:
+        {
+            GoASTBinaryExpr *n = llvm::cast<GoASTBinaryExpr>(this);
+            (void)n;
+            v(n->m_x_up.get());
+            v(n->m_y_up.get());
+            return;
+        }
+    case eBlockStmt:
+        {
+            GoASTBlockStmt *n = llvm::cast<GoASTBlockStmt>(this);
+            (void)n;
+            for (auto& e : n->m_list) { v(e.get()); }
+            return;
+        }
+    case eIdent:
+        {
+            GoASTIdent *n = llvm::cast<GoASTIdent>(this);
+            (void)n;
+            return;
+        }
+    case eBranchStmt:
+        {
+            GoASTBranchStmt *n = llvm::cast<GoASTBranchStmt>(this);
+            (void)n;
+            v(n->m_label_up.get());
+            return;
+        }
+    case eCallExpr:
+        {
+            GoASTCallExpr *n = llvm::cast<GoASTCallExpr>(this);
+            (void)n;
+            v(n->m_fun_up.get());
+            for (auto& e : n->m_args) { v(e.get()); }
+            return;
+        }
+    case eCaseClause:
+        {
+            GoASTCaseClause *n = llvm::cast<GoASTCaseClause>(this);
+            (void)n;
+            for (auto& e : n->m_list) { v(e.get()); }
+            for (auto& e : n->m_body) { v(e.get()); }
+            return;
+        }
+    case eChanType:
+        {
+            GoASTChanType *n = llvm::cast<GoASTChanType>(this);
+            (void)n;
+            v(n->m_value_up.get());
+            return;
+        }
+    case eCommClause:
+        {
+            GoASTCommClause *n = llvm::cast<GoASTCommClause>(this);
+            (void)n;
+            v(n->m_comm_up.get());
+            for (auto& e : n->m_body) { v(e.get()); }
+            return;
+        }
+    case eCompositeLit:
+        {
+            GoASTCompositeLit *n = llvm::cast<GoASTCompositeLit>(this);
+            (void)n;
+            v(n->m_type_up.get());
+            for (auto& e : n->m_elts) { v(e.get()); }
+            return;
+        }
+    case eDeclStmt:
+        {
+            GoASTDeclStmt *n = llvm::cast<GoASTDeclStmt>(this);
+            (void)n;
+            v(n->m_decl_up.get());
+            return;
+        }
+    case eDeferStmt:
+        {
+            GoASTDeferStmt *n = llvm::cast<GoASTDeferStmt>(this);
+            (void)n;
+            v(n->m_call_up.get());
+            return;
+        }
+    case eEllipsis:
+        {
+            GoASTEllipsis *n = llvm::cast<GoASTEllipsis>(this);
+            (void)n;
+            v(n->m_elt_up.get());
+            return;
+        }
+    case eExprStmt:
+        {
+            GoASTExprStmt *n = llvm::cast<GoASTExprStmt>(this);
+            (void)n;
+            v(n->m_x_up.get());
+            return;
+        }
+    case eField:
+        {
+            GoASTField *n = llvm::cast<GoASTField>(this);
+            (void)n;
+            for (auto& e : n->m_names) { v(e.get()); }
+            v(n->m_type_up.get());
+            v(n->m_tag_up.get());
+            return;
+        }
+    case eFieldList:
+        {
+            GoASTFieldList *n = llvm::cast<GoASTFieldList>(this);
+            (void)n;
+            for (auto& e : n->m_list) { v(e.get()); }
+            return;
+        }
+    case eForStmt:
+        {
+            GoASTForStmt *n = llvm::cast<GoASTForStmt>(this);
+            (void)n;
+            v(n->m_init_up.get());
+            v(n->m_cond_up.get());
+            v(n->m_post_up.get());
+            v(n->m_body_up.get());
+            return;
+        }
+    case eFuncType:
+        {
+            GoASTFuncType *n = llvm::cast<GoASTFuncType>(this);
+            (void)n;
+            v(n->m_params_up.get());
+            v(n->m_results_up.get());
+            return;
+        }
+    case eFuncDecl:
+        {
+            GoASTFuncDecl *n = llvm::cast<GoASTFuncDecl>(this);
+            (void)n;
+            v(n->m_recv_up.get());
+            v(n->m_name_up.get());
+            v(n->m_type_up.get());
+            v(n->m_body_up.get());
+            return;
+        }
+    case eFuncLit:
+        {
+            GoASTFuncLit *n = llvm::cast<GoASTFuncLit>(this);
+            (void)n;
+            v(n->m_type_up.get());
+            v(n->m_body_up.get());
+            return;
+        }
+    case eGenDecl:
+        {
+            GoASTGenDecl *n = llvm::cast<GoASTGenDecl>(this);
+            (void)n;
+            for (auto& e : n->m_specs) { v(e.get()); }
+            return;
+        }
+    case eGoStmt:
+        {
+            GoASTGoStmt *n = llvm::cast<GoASTGoStmt>(this);
+            (void)n;
+            v(n->m_call_up.get());
+            return;
+        }
+    case eIfStmt:
+        {
+            GoASTIfStmt *n = llvm::cast<GoASTIfStmt>(this);
+            (void)n;
+            v(n->m_init_up.get());
+            v(n->m_cond_up.get());
+            v(n->m_body_up.get());
+            v(n->m_els_up.get());
+            return;
+        }
+    case eImportSpec:
+        {
+            GoASTImportSpec *n = llvm::cast<GoASTImportSpec>(this);
+            (void)n;
+            v(n->m_name_up.get());
+            v(n->m_path_up.get());
+            return;
+        }
+    case eIncDecStmt:
+        {
+            GoASTIncDecStmt *n = llvm::cast<GoASTIncDecStmt>(this);
+            (void)n;
+            v(n->m_x_up.get());
+            return;
+        }
+    case eIndexExpr:
+        {
+            GoASTIndexExpr *n = llvm::cast<GoASTIndexExpr>(this);
+            (void)n;
+            v(n->m_x_up.get());
+            v(n->m_index_up.get());
+            return;
+        }
+    case eInterfaceType:
+        {
+            GoASTInterfaceType *n = llvm::cast<GoASTInterfaceType>(this);
+            (void)n;
+            v(n->m_methods_up.get());
+            return;
+        }
+    case eKeyValueExpr:
+        {
+            GoASTKeyValueExpr *n = llvm::cast<GoASTKeyValueExpr>(this);
+            (void)n;
+            v(n->m_key_up.get());
+            v(n->m_value_up.get());
+            return;
+        }
+    case eLabeledStmt:
+        {
+            GoASTLabeledStmt *n = llvm::cast<GoASTLabeledStmt>(this);
+            (void)n;
+            v(n->m_label_up.get());
+            v(n->m_stmt_up.get());
+            return;
+        }
+    case eMapType:
+        {
+            GoASTMapType *n = llvm::cast<GoASTMapType>(this);
+            (void)n;
+            v(n->m_key_up.get());
+            v(n->m_value_up.get());
+            return;
+        }
+    case eParenExpr:
+        {
+            GoASTParenExpr *n = llvm::cast<GoASTParenExpr>(this);
+            (void)n;
+            v(n->m_x_up.get());
+            return;
+        }
+    case eRangeStmt:
+        {
+            GoASTRangeStmt *n = llvm::cast<GoASTRangeStmt>(this);
+            (void)n;
+            v(n->m_key_up.get());
+            v(n->m_value_up.get());
+            v(n->m_x_up.get());
+            v(n->m_body_up.get());
+            return;
+        }
+    case eReturnStmt:
+        {
+            GoASTReturnStmt *n = llvm::cast<GoASTReturnStmt>(this);
+            (void)n;
+            for (auto& e : n->m_results) { v(e.get()); }
+            return;
+        }
+    case eSelectStmt:
+        {
+            GoASTSelectStmt *n = llvm::cast<GoASTSelectStmt>(this);
+            (void)n;
+            v(n->m_body_up.get());
+            return;
+        }
+    case eSelectorExpr:
+        {
+            GoASTSelectorExpr *n = llvm::cast<GoASTSelectorExpr>(this);
+            (void)n;
+            v(n->m_x_up.get());
+            v(n->m_sel_up.get());
+            return;
+        }
+    case eSendStmt:
+        {
+            GoASTSendStmt *n = llvm::cast<GoASTSendStmt>(this);
+            (void)n;
+            v(n->m_chan_up.get());
+            v(n->m_value_up.get());
+            return;
+        }
+    case eSliceExpr:
+        {
+            GoASTSliceExpr *n = llvm::cast<GoASTSliceExpr>(this);
+            (void)n;
+            v(n->m_x_up.get());
+            v(n->m_low_up.get());
+            v(n->m_high_up.get());
+            v(n->m_max_up.get());
+            return;
+        }
+    case eStarExpr:
+        {
+            GoASTStarExpr *n = llvm::cast<GoASTStarExpr>(this);
+            (void)n;
+            v(n->m_x_up.get());
+            return;
+        }
+    case eStructType:
+        {
+            GoASTStructType *n = llvm::cast<GoASTStructType>(this);
+            (void)n;
+            v(n->m_fields_up.get());
+            return;
+        }
+    case eSwitchStmt:
+        {
+            GoASTSwitchStmt *n = llvm::cast<GoASTSwitchStmt>(this);
+            (void)n;
+            v(n->m_init_up.get());
+            v(n->m_tag_up.get());
+            v(n->m_body_up.get());
+            return;
+        }
+    case eTypeAssertExpr:
+        {
+            GoASTTypeAssertExpr *n = llvm::cast<GoASTTypeAssertExpr>(this);
+            (void)n;
+            v(n->m_x_up.get());
+            v(n->m_type_up.get());
+            return;
+        }
+    case eTypeSpec:
+        {
+            GoASTTypeSpec *n = llvm::cast<GoASTTypeSpec>(this);
+            (void)n;
+            v(n->m_name_up.get());
+            v(n->m_type_up.get());
+            return;
+        }
+    case eTypeSwitchStmt:
+        {
+            GoASTTypeSwitchStmt *n = llvm::cast<GoASTTypeSwitchStmt>(this);
+            (void)n;
+            v(n->m_init_up.get());
+            v(n->m_assign_up.get());
+            v(n->m_body_up.get());
+            return;
+        }
+    case eUnaryExpr:
+        {
+            GoASTUnaryExpr *n = llvm::cast<GoASTUnaryExpr>(this);
+            (void)n;
+            v(n->m_x_up.get());
+            return;
+        }
+    case eValueSpec:
+        {
+            GoASTValueSpec *n = llvm::cast<GoASTValueSpec>(this);
+            (void)n;
+            for (auto& e : n->m_names) { v(e.get()); }
+            v(n->m_type_up.get());
+            for (auto& e : n->m_values) { v(e.get()); }
+            return;
+        }
+
+        case eEmptyStmt:
+        case eBadDecl:
+        case eBadExpr:
+        case eBadStmt:
+          break;
+    }
+}
+
+}  // namespace lldb_private
+
+#endif
+

Added: lldb/trunk/source/Plugins/ExpressionParser/Go/GoLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Go/GoLexer.cpp?rev=251820&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Go/GoLexer.cpp (added)
+++ lldb/trunk/source/Plugins/ExpressionParser/Go/GoLexer.cpp Mon Nov  2 13:30:40 2015
@@ -0,0 +1,402 @@
+//===-- GoLexer.cpp ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+
+#include "GoLexer.h"
+
+using namespace lldb_private;
+
+llvm::StringMap<GoLexer::TokenType> *GoLexer::m_keywords;
+
+GoLexer::GoLexer(const char *src) : m_src(src), m_end(src + strlen(src)), m_last_token(TOK_INVALID, "")
+{
+}
+
+bool
+GoLexer::SkipWhitespace()
+{
+    bool saw_newline = false;
+    for (; m_src < m_end; ++m_src)
+    {
+        if (*m_src == '\n')
+            saw_newline = true;
+        if (*m_src == '/' && !SkipComment())
+            return saw_newline;
+        else if (!IsWhitespace(*m_src))
+            return saw_newline;
+    }
+    return saw_newline;
+}
+
+bool
+GoLexer::SkipComment()
+{
+    if (m_src[0] == '/' && m_src[1] == '/')
+    {
+        for (const char *c = m_src + 2; c < m_end; ++c)
+        {
+            if (*c == '\n')
+            {
+                m_src = c - 1;
+                return true;
+            }
+        }
+        return true;
+    }
+    else if (m_src[0] == '/' && m_src[1] == '*')
+    {
+        for (const char *c = m_src + 2; c < m_end; ++c)
+        {
+            if (c[0] == '*' && c[1] == '/')
+            {
+                m_src = c + 1;
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+const GoLexer::Token &
+GoLexer::Lex()
+{
+    bool newline = SkipWhitespace();
+    const char *start = m_src;
+    m_last_token.m_type = InternalLex(newline);
+    m_last_token.m_value = llvm::StringRef(start, m_src - start);
+    return m_last_token;
+}
+
+GoLexer::TokenType
+GoLexer::InternalLex(bool newline)
+{
+    if (m_src >= m_end)
+    {
+        return TOK_EOF;
+    }
+    if (newline)
+    {
+        switch (m_last_token.m_type)
+        {
+            case TOK_IDENTIFIER:
+            case LIT_FLOAT:
+            case LIT_IMAGINARY:
+            case LIT_INTEGER:
+            case LIT_RUNE:
+            case LIT_STRING:
+            case KEYWORD_BREAK:
+            case KEYWORD_CONTINUE:
+            case KEYWORD_FALLTHROUGH:
+            case KEYWORD_RETURN:
+            case OP_PLUS_PLUS:
+            case OP_MINUS_MINUS:
+            case OP_RPAREN:
+            case OP_RBRACK:
+            case OP_RBRACE:
+                return OP_SEMICOLON;
+            default:
+                break;
+        }
+    }
+    char c = *m_src;
+    switch (c)
+    {
+        case '0':
+        case '1':
+        case '2':
+        case '3':
+        case '4':
+        case '5':
+        case '6':
+        case '7':
+        case '8':
+        case '9':
+            return DoNumber();
+        case '+':
+        case '-':
+        case '*':
+        case '/':
+        case '%':
+        case '&':
+        case '|':
+        case '^':
+        case '<':
+        case '>':
+        case '!':
+        case ':':
+        case ';':
+        case '(':
+        case ')':
+        case '[':
+        case ']':
+        case '{':
+        case '}':
+        case ',':
+        case '=':
+            return DoOperator();
+        case '.':
+            if (IsDecimal(m_src[1]))
+                return DoNumber();
+            return DoOperator();
+        case '$':
+            // For lldb persistent vars.
+            return DoIdent();
+        case '"':
+        case '`':
+            return DoString();
+        case '\'':
+            return DoRune();
+        default:
+            break;
+    }
+    if (IsLetterOrDigit(c))
+        return DoIdent();
+    ++m_src;
+    return TOK_INVALID;
+}
+
+GoLexer::TokenType
+GoLexer::DoOperator()
+{
+    TokenType t = TOK_INVALID;
+    if (m_end - m_src > 2)
+    {
+        t = LookupKeyword(llvm::StringRef(m_src, 3));
+        if (t != TOK_INVALID)
+            m_src += 3;
+    }
+    if (t == TOK_INVALID && m_end - m_src > 1)
+    {
+        t = LookupKeyword(llvm::StringRef(m_src, 2));
+        if (t != TOK_INVALID)
+            m_src += 2;
+    }
+    if (t == TOK_INVALID)
+    {
+        t = LookupKeyword(llvm::StringRef(m_src, 1));
+        ++m_src;
+    }
+    return t;
+}
+
+GoLexer::TokenType
+GoLexer::DoIdent()
+{
+    const char *start = m_src++;
+    while (m_src < m_end && IsLetterOrDigit(*m_src))
+    {
+        ++m_src;
+    }
+    TokenType kw = LookupKeyword(llvm::StringRef(start, m_src - start));
+    if (kw != TOK_INVALID)
+        return kw;
+    return TOK_IDENTIFIER;
+}
+
+GoLexer::TokenType
+GoLexer::DoNumber()
+{
+    if (m_src[0] == '0' && (m_src[1] == 'x' || m_src[1] == 'X'))
+    {
+        m_src += 2;
+        while (IsHexChar(*m_src))
+            ++m_src;
+        return LIT_INTEGER;
+    }
+    bool dot_ok = true;
+    bool e_ok = true;
+    while (true)
+    {
+        while (IsDecimal(*m_src))
+            ++m_src;
+        switch (*m_src)
+        {
+            case 'i':
+                ++m_src;
+                return LIT_IMAGINARY;
+            case '.':
+                if (!dot_ok)
+                    return LIT_FLOAT;
+                ++m_src;
+                dot_ok = false;
+                break;
+            case 'e':
+            case 'E':
+                if (!e_ok)
+                    return LIT_FLOAT;
+                dot_ok = e_ok = false;
+                ++m_src;
+                if (*m_src == '+' || *m_src == '-')
+                    ++m_src;
+                break;
+            default:
+                if (dot_ok)
+                    return LIT_INTEGER;
+                return LIT_FLOAT;
+        }
+    }
+}
+
+GoLexer::TokenType
+GoLexer::DoRune()
+{
+    while (++m_src < m_end)
+    {
+        switch (*m_src)
+        {
+            case '\'':
+                ++m_src;
+                return LIT_RUNE;
+            case '\n':
+                return TOK_INVALID;
+            case '\\':
+                if (m_src[1] == '\n')
+                    return TOK_INVALID;
+                ++m_src;
+        }
+    }
+    return TOK_INVALID;
+}
+
+GoLexer::TokenType
+GoLexer::DoString()
+{
+    if (*m_src == '`')
+    {
+        while (++m_src < m_end)
+        {
+            if (*m_src == '`')
+            {
+                ++m_src;
+                return LIT_STRING;
+            }
+        }
+        return TOK_INVALID;
+    }
+    while (++m_src < m_end)
+    {
+        switch (*m_src)
+        {
+            case '"':
+                ++m_src;
+                return LIT_STRING;
+            case '\n':
+                return TOK_INVALID;
+            case '\\':
+                if (m_src[1] == '\n')
+                    return TOK_INVALID;
+                ++m_src;
+        }
+    }
+    return TOK_INVALID;
+}
+
+GoLexer::TokenType
+GoLexer::LookupKeyword(llvm::StringRef id)
+{
+    if (m_keywords == nullptr)
+        m_keywords = InitKeywords();
+    const auto &it = m_keywords->find(id);
+    if (it == m_keywords->end())
+        return TOK_INVALID;
+    return it->second;
+}
+
+llvm::StringRef
+GoLexer::LookupToken(TokenType t)
+{
+    if (m_keywords == nullptr)
+        m_keywords = InitKeywords();
+    for (const auto &e : *m_keywords)
+    {
+        if (e.getValue() == t)
+            return e.getKey();
+    }
+    return "";
+}
+
+llvm::StringMap<GoLexer::TokenType> *
+GoLexer::InitKeywords()
+{
+    auto &result = *new llvm::StringMap<TokenType>(128);
+    result["break"] = KEYWORD_BREAK;
+    result["default"] = KEYWORD_DEFAULT;
+    result["func"] = KEYWORD_FUNC;
+    result["interface"] = KEYWORD_INTERFACE;
+    result["select"] = KEYWORD_SELECT;
+    result["case"] = KEYWORD_CASE;
+    result["defer"] = KEYWORD_DEFER;
+    result["go"] = KEYWORD_GO;
+    result["map"] = KEYWORD_MAP;
+    result["struct"] = KEYWORD_STRUCT;
+    result["chan"] = KEYWORD_CHAN;
+    result["else"] = KEYWORD_ELSE;
+    result["goto"] = KEYWORD_GOTO;
+    result["package"] = KEYWORD_PACKAGE;
+    result["switch"] = KEYWORD_SWITCH;
+    result["const"] = KEYWORD_CONST;
+    result["fallthrough"] = KEYWORD_FALLTHROUGH;
+    result["if"] = KEYWORD_IF;
+    result["range"] = KEYWORD_RANGE;
+    result["type"] = KEYWORD_TYPE;
+    result["continue"] = KEYWORD_CONTINUE;
+    result["for"] = KEYWORD_FOR;
+    result["import"] = KEYWORD_IMPORT;
+    result["return"] = KEYWORD_RETURN;
+    result["var"] = KEYWORD_VAR;
+    result["+"] = OP_PLUS;
+    result["-"] = OP_MINUS;
+    result["*"] = OP_STAR;
+    result["/"] = OP_SLASH;
+    result["%"] = OP_PERCENT;
+    result["&"] = OP_AMP;
+    result["|"] = OP_PIPE;
+    result["^"] = OP_CARET;
+    result["<<"] = OP_LSHIFT;
+    result[">>"] = OP_RSHIFT;
+    result["&^"] = OP_AMP_CARET;
+    result["+="] = OP_PLUS_EQ;
+    result["-="] = OP_MINUS_EQ;
+    result["*="] = OP_STAR_EQ;
+    result["/="] = OP_SLASH_EQ;
+    result["%="] = OP_PERCENT_EQ;
+    result["&="] = OP_AMP_EQ;
+    result["|="] = OP_PIPE_EQ;
+    result["^="] = OP_CARET_EQ;
+    result["<<="] = OP_LSHIFT_EQ;
+    result[">>="] = OP_RSHIFT_EQ;
+    result["&^="] = OP_AMP_CARET_EQ;
+    result["&&"] = OP_AMP_AMP;
+    result["||"] = OP_PIPE_PIPE;
+    result["<-"] = OP_LT_MINUS;
+    result["++"] = OP_PLUS_PLUS;
+    result["--"] = OP_MINUS_MINUS;
+    result["=="] = OP_EQ_EQ;
+    result["<"] = OP_LT;
+    result[">"] = OP_GT;
+    result["="] = OP_EQ;
+    result["!"] = OP_BANG;
+    result["!="] = OP_BANG_EQ;
+    result["<="] = OP_LT_EQ;
+    result[">="] = OP_GT_EQ;
+    result[":="] = OP_COLON_EQ;
+    result["..."] = OP_DOTS;
+    result["("] = OP_LPAREN;
+    result["["] = OP_LBRACK;
+    result["{"] = OP_LBRACE;
+    result[","] = OP_COMMA;
+    result["."] = OP_DOT;
+    result[")"] = OP_RPAREN;
+    result["]"] = OP_RBRACK;
+    result["}"] = OP_RBRACE;
+    result[";"] = OP_SEMICOLON;
+    result[":"] = OP_COLON;
+    return &result;
+}

Added: lldb/trunk/source/Plugins/ExpressionParser/Go/GoLexer.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Go/GoLexer.h?rev=251820&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Go/GoLexer.h (added)
+++ lldb/trunk/source/Plugins/ExpressionParser/Go/GoLexer.h Mon Nov  2 13:30:40 2015
@@ -0,0 +1,201 @@
+//===-- GoLexer.h -----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GoLexer_h
+#define liblldb_GoLexer_h
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringMap.h"
+
+namespace lldb_private
+{
+
+class GoLexer
+{
+  public:
+    explicit GoLexer(const char *src);
+
+    enum TokenType
+    {
+        TOK_EOF,
+        TOK_INVALID,
+        TOK_IDENTIFIER,
+        LIT_INTEGER,
+        LIT_FLOAT,
+        LIT_IMAGINARY,
+        LIT_RUNE,
+        LIT_STRING,
+        KEYWORD_BREAK,
+        KEYWORD_DEFAULT,
+        KEYWORD_FUNC,
+        KEYWORD_INTERFACE,
+        KEYWORD_SELECT,
+        KEYWORD_CASE,
+        KEYWORD_DEFER,
+        KEYWORD_GO,
+        KEYWORD_MAP,
+        KEYWORD_STRUCT,
+        KEYWORD_CHAN,
+        KEYWORD_ELSE,
+        KEYWORD_GOTO,
+        KEYWORD_PACKAGE,
+        KEYWORD_SWITCH,
+        KEYWORD_CONST,
+        KEYWORD_FALLTHROUGH,
+        KEYWORD_IF,
+        KEYWORD_RANGE,
+        KEYWORD_TYPE,
+        KEYWORD_CONTINUE,
+        KEYWORD_FOR,
+        KEYWORD_IMPORT,
+        KEYWORD_RETURN,
+        KEYWORD_VAR,
+        OP_PLUS,
+        OP_MINUS,
+        OP_STAR,
+        OP_SLASH,
+        OP_PERCENT,
+        OP_AMP,
+        OP_PIPE,
+        OP_CARET,
+        OP_LSHIFT,
+        OP_RSHIFT,
+        OP_AMP_CARET,
+        OP_PLUS_EQ,
+        OP_MINUS_EQ,
+        OP_STAR_EQ,
+        OP_SLASH_EQ,
+        OP_PERCENT_EQ,
+        OP_AMP_EQ,
+        OP_PIPE_EQ,
+        OP_CARET_EQ,
+        OP_LSHIFT_EQ,
+        OP_RSHIFT_EQ,
+        OP_AMP_CARET_EQ,
+        OP_AMP_AMP,
+        OP_PIPE_PIPE,
+        OP_LT_MINUS,
+        OP_PLUS_PLUS,
+        OP_MINUS_MINUS,
+        OP_EQ_EQ,
+        OP_LT,
+        OP_GT,
+        OP_EQ,
+        OP_BANG,
+        OP_BANG_EQ,
+        OP_LT_EQ,
+        OP_GT_EQ,
+        OP_COLON_EQ,
+        OP_DOTS,
+        OP_LPAREN,
+        OP_LBRACK,
+        OP_LBRACE,
+        OP_COMMA,
+        OP_DOT,
+        OP_RPAREN,
+        OP_RBRACK,
+        OP_RBRACE,
+        OP_SEMICOLON,
+        OP_COLON,
+    };
+
+    struct Token
+    {
+        explicit Token(TokenType t, llvm::StringRef text) : m_type(t), m_value(text) {}
+        TokenType m_type;
+        llvm::StringRef m_value;
+    };
+
+    const Token &Lex();
+
+    size_t
+    BytesRemaining() const
+    {
+        return m_end - m_src;
+    }
+    llvm::StringRef
+    GetString(int len) const
+    {
+        return llvm::StringRef(m_src, len);
+    }
+
+    static TokenType LookupKeyword(llvm::StringRef id);
+    static llvm::StringRef LookupToken(TokenType t);
+
+  private:
+    bool
+    IsDecimal(char c)
+    {
+        return c >= '0' && c <= '9';
+    }
+    bool
+    IsHexChar(char c)
+    {
+        if (c >= '0' && c <= '9')
+            return true;
+        if (c >= 'A' && c <= 'F')
+            return true;
+        if (c >= 'a' && c <= 'f')
+            return true;
+        return false;
+    }
+    bool
+    IsLetterOrDigit(char c)
+    {
+        if (c >= 'a' && c <= 'z')
+            return true;
+        if (c >= 'A' && c <= 'Z')
+            return true;
+        if (c == '_')
+            return true;
+        if (c >= '0' && c <= '9')
+            return true;
+        // Treat all non-ascii chars as letters for simplicity.
+        return 0 != (c & 0x80);
+    }
+    bool
+    IsWhitespace(char c)
+    {
+        switch (c)
+        {
+            case ' ':
+            case '\t':
+            case '\r':
+                return true;
+        }
+        return false;
+    }
+
+    bool SkipWhitespace();
+    bool SkipComment();
+
+    TokenType InternalLex(bool newline);
+
+    TokenType DoOperator();
+
+    TokenType DoIdent();
+
+    TokenType DoNumber();
+
+    TokenType DoRune();
+
+    TokenType DoString();
+
+    static llvm::StringMap<TokenType> *InitKeywords();
+
+    static llvm::StringMap<TokenType> *m_keywords;
+
+    const char *m_src;
+    const char *m_end;
+    Token m_last_token;
+};
+
+} // namespace lldb_private
+
+#endif

Added: lldb/trunk/source/Plugins/ExpressionParser/Go/GoParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Go/GoParser.cpp?rev=251820&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Go/GoParser.cpp (added)
+++ lldb/trunk/source/Plugins/ExpressionParser/Go/GoParser.cpp Mon Nov  2 13:30:40 2015
@@ -0,0 +1,1035 @@
+//===-- GoParser.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <vector>
+
+#include "GoParser.h"
+
+#include "lldb/Core/Error.h"
+#include "llvm/ADT/SmallString.h"
+#include "Plugins/ExpressionParser/Go/GoAST.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+namespace
+{
+llvm::StringRef
+DescribeToken(GoLexer::TokenType t)
+{
+    switch (t)
+    {
+        case GoLexer::TOK_EOF:
+            return "<eof>";
+        case GoLexer::TOK_IDENTIFIER:
+            return "identifier";
+        case GoLexer::LIT_FLOAT:
+            return "float";
+        case GoLexer::LIT_IMAGINARY:
+            return "imaginary";
+        case GoLexer::LIT_INTEGER:
+            return "integer";
+        case GoLexer::LIT_RUNE:
+            return "rune";
+        case GoLexer::LIT_STRING:
+            return "string";
+        default:
+            return GoLexer::LookupToken(t);
+    }
+}
+} // namespace
+
+class GoParser::Rule
+{
+  public:
+    Rule(llvm::StringRef name, GoParser *p) : m_name(name), m_parser(p), m_pos(p->m_pos) {}
+
+    std::nullptr_t
+    error()
+    {
+        if (!m_parser->m_failed)
+        {
+            // Set m_error in case this is the top level.
+            if (m_parser->m_last_tok == GoLexer::TOK_INVALID)
+                m_parser->m_error = m_parser->m_last;
+            else
+                m_parser->m_error = DescribeToken(m_parser->m_last_tok);
+            // And set m_last in case it isn't.
+            m_parser->m_last = m_name;
+            m_parser->m_last_tok = GoLexer::TOK_INVALID;
+            m_parser->m_pos = m_pos;
+        }
+        return nullptr;
+    }
+
+  private:
+    llvm::StringRef m_name;
+    GoParser *m_parser;
+    size_t m_pos;
+};
+
+GoParser::GoParser(const char *src) : m_lexer(src), m_pos(0), m_failed(false)
+{
+}
+
+GoASTStmt *
+GoParser::Statement()
+{
+    Rule r("Statement", this);
+    GoLexer::TokenType t = peek();
+    GoASTStmt *ret = nullptr;
+    switch (t)
+    {
+        case GoLexer::TOK_EOF:
+        case GoLexer::OP_SEMICOLON:
+        case GoLexer::OP_RPAREN:
+        case GoLexer::OP_RBRACE:
+        case GoLexer::TOK_INVALID:
+            return EmptyStmt();
+        case GoLexer::OP_LBRACE:
+            return Block();
+
+        /*      TODO:
+    case GoLexer::KEYWORD_GO:
+        return GoStmt();
+    case GoLexer::KEYWORD_RETURN:
+        return ReturnStmt();
+    case GoLexer::KEYWORD_BREAK:
+    case GoLexer::KEYWORD_CONTINUE:
+    case GoLexer::KEYWORD_GOTO:
+    case GoLexer::KEYWORD_FALLTHROUGH:
+        return BranchStmt();
+    case GoLexer::KEYWORD_IF:
+        return IfStmt();
+    case GoLexer::KEYWORD_SWITCH:
+        return SwitchStmt();
+    case GoLexer::KEYWORD_SELECT:
+        return SelectStmt();
+    case GoLexer::KEYWORD_FOR:
+        return ForStmt();
+    case GoLexer::KEYWORD_DEFER:
+        return DeferStmt();
+    case GoLexer::KEYWORD_CONST:
+    case GoLexer::KEYWORD_TYPE:
+    case GoLexer::KEYWORD_VAR:
+        return DeclStmt();
+    case GoLexer::TOK_IDENTIFIER:
+        if ((ret = LabeledStmt()) ||
+            (ret = ShortVarDecl()))
+        {
+            return ret;
+        }
+*/
+        default:
+            break;
+    }
+    GoASTExpr *expr = Expression();
+    if (expr == nullptr)
+        return r.error();
+    if (/*(ret = SendStmt(expr)) ||*/
+        (ret = IncDecStmt(expr)) || (ret = Assignment(expr)) || (ret = ExpressionStmt(expr)))
+    {
+        return ret;
+    }
+    delete expr;
+    return r.error();
+}
+
+GoASTStmt *
+GoParser::ExpressionStmt(GoASTExpr *e)
+{
+    if (Semicolon())
+        return new GoASTExprStmt(e);
+    return nullptr;
+}
+
+GoASTStmt *
+GoParser::IncDecStmt(GoASTExpr *e)
+{
+    Rule r("IncDecStmt", this);
+    if (match(GoLexer::OP_PLUS_PLUS))
+        return Semicolon() ? new GoASTIncDecStmt(e, GoLexer::OP_PLUS_PLUS) : r.error();
+    if (match(GoLexer::OP_MINUS_MINUS))
+        return Semicolon() ? new GoASTIncDecStmt(e, GoLexer::OP_MINUS_MINUS) : r.error();
+    return nullptr;
+}
+
+GoASTStmt *
+GoParser::Assignment(lldb_private::GoASTExpr *e)
+{
+    Rule r("Assignment", this);
+    std::vector<std::unique_ptr<GoASTExpr>> lhs;
+    for (GoASTExpr *l = MoreExpressionList(); l; l = MoreExpressionList())
+        lhs.push_back(std::unique_ptr<GoASTExpr>(l));
+    switch (peek())
+    {
+        case GoLexer::OP_EQ:
+        case GoLexer::OP_PLUS_EQ:
+        case GoLexer::OP_MINUS_EQ:
+        case GoLexer::OP_PIPE_EQ:
+        case GoLexer::OP_CARET_EQ:
+        case GoLexer::OP_STAR_EQ:
+        case GoLexer::OP_SLASH_EQ:
+        case GoLexer::OP_PERCENT_EQ:
+        case GoLexer::OP_LSHIFT_EQ:
+        case GoLexer::OP_RSHIFT_EQ:
+        case GoLexer::OP_AMP_EQ:
+        case GoLexer::OP_AMP_CARET_EQ:
+            break;
+        default:
+            return r.error();
+    }
+    // We don't want to own e until we know this is an assignment.
+    std::unique_ptr<GoASTAssignStmt> stmt(new GoASTAssignStmt(false));
+    stmt->AddLhs(e);
+    for (auto &l : lhs)
+        stmt->AddLhs(l.release());
+    for (GoASTExpr *r = Expression(); r; r = MoreExpressionList())
+        stmt->AddRhs(r);
+    if (!Semicolon() || stmt->NumRhs() == 0)
+        return new GoASTBadStmt;
+    return stmt.release();
+}
+
+GoASTStmt *
+GoParser::EmptyStmt()
+{
+    if (match(GoLexer::TOK_EOF))
+        return nullptr;
+    if (Semicolon())
+        return new GoASTEmptyStmt;
+    return nullptr;
+}
+
+GoASTStmt *
+GoParser::GoStmt()
+{
+    if (match(GoLexer::KEYWORD_GO))
+    {
+        if (GoASTCallExpr *e = llvm::dyn_cast_or_null<GoASTCallExpr>(Expression()))
+        {
+            return FinishStmt(new GoASTGoStmt(e));
+        }
+        m_last = "call expression";
+        m_failed = true;
+        return new GoASTBadStmt();
+    }
+    return nullptr;
+}
+
+GoASTStmt *
+GoParser::ReturnStmt()
+{
+    if (match(GoLexer::KEYWORD_RETURN))
+    {
+        std::unique_ptr<GoASTReturnStmt> r(new GoASTReturnStmt());
+        for (GoASTExpr *e = Expression(); e; e = MoreExpressionList())
+            r->AddResults(e);
+        return FinishStmt(r.release());
+    }
+    return nullptr;
+}
+
+GoASTStmt *
+GoParser::BranchStmt()
+{
+    GoLexer::Token *tok;
+    if ((tok = match(GoLexer::KEYWORD_BREAK)) || (tok = match(GoLexer::KEYWORD_CONTINUE)) ||
+        (tok = match(GoLexer::KEYWORD_GOTO)))
+    {
+        auto *e = Identifier();
+        if (tok->m_type == GoLexer::KEYWORD_GOTO && !e)
+            return syntaxerror();
+        return FinishStmt(new GoASTBranchStmt(e, tok->m_type));
+    }
+    if ((tok = match(GoLexer::KEYWORD_FALLTHROUGH)))
+        return FinishStmt(new GoASTBranchStmt(nullptr, tok->m_type));
+
+    return nullptr;
+}
+
+GoASTIdent *
+GoParser::Identifier()
+{
+    if (auto *tok = match(GoLexer::TOK_IDENTIFIER))
+        return new GoASTIdent(*tok);
+    return nullptr;
+}
+
+GoASTExpr *
+GoParser::MoreExpressionList()
+{
+    if (match(GoLexer::OP_COMMA))
+    {
+        auto *e = Expression();
+        if (!e)
+            return syntaxerror();
+        return e;
+    }
+    return nullptr;
+}
+
+GoASTIdent *
+GoParser::MoreIdentifierList()
+{
+    if (match(GoLexer::OP_COMMA))
+    {
+        auto *i = Identifier();
+        if (!i)
+            return syntaxerror();
+        return i;
+    }
+    return nullptr;
+}
+
+GoASTExpr *
+GoParser::Expression()
+{
+    Rule r("Expression", this);
+    if (GoASTExpr *ret = OrExpr())
+        return ret;
+    return r.error();
+}
+
+GoASTExpr *
+GoParser::UnaryExpr()
+{
+    switch (peek())
+    {
+        case GoLexer::OP_PLUS:
+        case GoLexer::OP_MINUS:
+        case GoLexer::OP_BANG:
+        case GoLexer::OP_CARET:
+        case GoLexer::OP_STAR:
+        case GoLexer::OP_AMP:
+        case GoLexer::OP_LT_MINUS:
+        {
+            const GoLexer::Token t = next();
+            if (GoASTExpr *e = UnaryExpr())
+            {
+                if (t.m_type == GoLexer::OP_STAR)
+                    return new GoASTStarExpr(e);
+                else
+                    return new GoASTUnaryExpr(t.m_type, e);
+            }
+            return syntaxerror();
+        }
+        default:
+            return PrimaryExpr();
+    }
+}
+
+GoASTExpr *
+GoParser::OrExpr()
+{
+    std::unique_ptr<GoASTExpr> l(AndExpr());
+    if (l)
+    {
+        while (match(GoLexer::OP_PIPE_PIPE))
+        {
+            GoASTExpr *r = AndExpr();
+            if (r)
+                l.reset(new GoASTBinaryExpr(l.release(), r, GoLexer::OP_PIPE_PIPE));
+            else
+                return syntaxerror();
+        }
+        return l.release();
+    }
+    return nullptr;
+}
+
+GoASTExpr *
+GoParser::AndExpr()
+{
+    std::unique_ptr<GoASTExpr> l(RelExpr());
+    if (l)
+    {
+        while (match(GoLexer::OP_AMP_AMP))
+        {
+            GoASTExpr *r = RelExpr();
+            if (r)
+                l.reset(new GoASTBinaryExpr(l.release(), r, GoLexer::OP_AMP_AMP));
+            else
+                return syntaxerror();
+        }
+        return l.release();
+    }
+    return nullptr;
+}
+
+GoASTExpr *
+GoParser::RelExpr()
+{
+    std::unique_ptr<GoASTExpr> l(AddExpr());
+    if (l)
+    {
+        for (GoLexer::Token *t; (t = match(GoLexer::OP_EQ_EQ)) || (t = match(GoLexer::OP_BANG_EQ)) ||
+                                (t = match(GoLexer::OP_LT)) || (t = match(GoLexer::OP_LT_EQ)) ||
+                                (t = match(GoLexer::OP_GT)) || (t = match(GoLexer::OP_GT_EQ));)
+        {
+            GoLexer::TokenType op = t->m_type;
+            GoASTExpr *r = AddExpr();
+            if (r)
+                l.reset(new GoASTBinaryExpr(l.release(), r, op));
+            else
+                return syntaxerror();
+        }
+        return l.release();
+    }
+    return nullptr;
+}
+
+GoASTExpr *
+GoParser::AddExpr()
+{
+    std::unique_ptr<GoASTExpr> l(MulExpr());
+    if (l)
+    {
+        for (GoLexer::Token *t; (t = match(GoLexer::OP_PLUS)) || (t = match(GoLexer::OP_MINUS)) ||
+                                (t = match(GoLexer::OP_PIPE)) || (t = match(GoLexer::OP_CARET));)
+        {
+            GoLexer::TokenType op = t->m_type;
+            GoASTExpr *r = MulExpr();
+            if (r)
+                l.reset(new GoASTBinaryExpr(l.release(), r, op));
+            else
+                return syntaxerror();
+        }
+        return l.release();
+    }
+    return nullptr;
+}
+
+GoASTExpr *
+GoParser::MulExpr()
+{
+    std::unique_ptr<GoASTExpr> l(UnaryExpr());
+    if (l)
+    {
+        for (GoLexer::Token *t; (t = match(GoLexer::OP_STAR)) || (t = match(GoLexer::OP_SLASH)) ||
+                                (t = match(GoLexer::OP_PERCENT)) || (t = match(GoLexer::OP_LSHIFT)) ||
+                                (t = match(GoLexer::OP_RSHIFT)) || (t = match(GoLexer::OP_AMP)) ||
+                                (t = match(GoLexer::OP_AMP_CARET));)
+        {
+            GoLexer::TokenType op = t->m_type;
+            GoASTExpr *r = UnaryExpr();
+            if (r)
+                l.reset(new GoASTBinaryExpr(l.release(), r, op));
+            else
+                return syntaxerror();
+        }
+        return l.release();
+    }
+    return nullptr;
+}
+
+GoASTExpr *
+GoParser::PrimaryExpr()
+{
+    GoASTExpr *l;
+    GoASTExpr *r;
+    (l = Conversion()) || (l = Operand());
+    if (!l)
+        return nullptr;
+    while ((r = Selector(l)) || (r = IndexOrSlice(l)) || (r = TypeAssertion(l)) || (r = Arguments(l)))
+    {
+        l = r;
+    }
+    return l;
+}
+
+GoASTExpr *
+GoParser::Operand()
+{
+    GoLexer::Token *lit;
+    if ((lit = match(GoLexer::LIT_INTEGER)) || (lit = match(GoLexer::LIT_FLOAT)) ||
+        (lit = match(GoLexer::LIT_IMAGINARY)) || (lit = match(GoLexer::LIT_RUNE)) || (lit = match(GoLexer::LIT_STRING)))
+        return new GoASTBasicLit(*lit);
+    if (match(GoLexer::OP_LPAREN))
+    {
+        GoASTExpr *e;
+        if (!((e = Expression()) && match(GoLexer::OP_RPAREN)))
+            return syntaxerror();
+        return e;
+    }
+    // MethodExpr should be handled by Selector
+    if (GoASTExpr *e = CompositeLit())
+        return e;
+    if (GoASTExpr *n = Name())
+        return n;
+    return FunctionLit();
+}
+
+GoASTExpr *
+GoParser::FunctionLit()
+{
+    if (!match(GoLexer::KEYWORD_FUNC))
+        return nullptr;
+    auto *sig = Signature();
+    if (!sig)
+        return syntaxerror();
+    auto *body = Block();
+    if (!body)
+    {
+        delete sig;
+        return syntaxerror();
+    }
+    return new GoASTFuncLit(sig, body);
+}
+
+GoASTBlockStmt *
+GoParser::Block()
+{
+    if (!match(GoLexer::OP_LBRACE))
+        return nullptr;
+    std::unique_ptr<GoASTBlockStmt> block(new GoASTBlockStmt);
+    for (auto *s = Statement(); s; s = Statement())
+        block->AddList(s);
+    if (!match(GoLexer::OP_RBRACE))
+        return syntaxerror();
+    return block.release();
+}
+
+GoASTExpr *
+GoParser::CompositeLit()
+{
+    Rule r("CompositeLit", this);
+    GoASTExpr *type;
+    (type = StructType()) || (type = ArrayOrSliceType(true)) || (type = MapType()) || (type = Name());
+    if (!type)
+        return r.error();
+    GoASTCompositeLit *lit = LiteralValue();
+    if (!lit)
+        return r.error();
+    lit->SetType(type);
+    return lit;
+}
+
+GoASTCompositeLit *
+GoParser::LiteralValue()
+{
+    if (!match(GoLexer::OP_LBRACE))
+        return nullptr;
+    std::unique_ptr<GoASTCompositeLit> lit(new GoASTCompositeLit);
+    for (GoASTExpr *e = Element(); e; e = Element())
+    {
+        lit->AddElts(e);
+        if (!match(GoLexer::OP_COMMA))
+            break;
+    }
+    if (!mustMatch(GoLexer::OP_RBRACE))
+        return nullptr;
+    return lit.release();
+}
+
+GoASTExpr *
+GoParser::Element()
+{
+    GoASTExpr *key;
+    if (!((key = Expression()) || (key = LiteralValue())))
+        return nullptr;
+    if (!match(GoLexer::OP_COLON))
+        return key;
+    GoASTExpr *value;
+    if ((value = Expression()) || (value = LiteralValue()))
+        return new GoASTKeyValueExpr(key, value);
+    delete key;
+    return syntaxerror();
+}
+
+GoASTExpr *
+GoParser::Selector(GoASTExpr *e)
+{
+    Rule r("Selector", this);
+    if (match(GoLexer::OP_DOT))
+    {
+        if (auto *name = Identifier())
+            return new GoASTSelectorExpr(e, name);
+    }
+    return r.error();
+}
+
+GoASTExpr *
+GoParser::IndexOrSlice(GoASTExpr *e)
+{
+    Rule r("IndexOrSlice", this);
+    if (match(GoLexer::OP_LBRACK))
+    {
+        std::unique_ptr<GoASTExpr> i1(Expression()), i2, i3;
+        bool slice = false;
+        if (match(GoLexer::OP_COLON))
+        {
+            slice = true;
+            i2.reset(Expression());
+            if (i2 && match(GoLexer::OP_COLON))
+            {
+                i3.reset(Expression());
+                if (!i3)
+                    return syntaxerror();
+            }
+        }
+        if (!(slice || i1))
+            return syntaxerror();
+        if (!mustMatch(GoLexer::OP_RBRACK))
+            return nullptr;
+        if (slice)
+        {
+            bool slice3 = i3.get();
+            return new GoASTSliceExpr(e, i1.release(), i2.release(), i3.release(), slice3);
+        }
+        return new GoASTIndexExpr(e, i1.release());
+    }
+    return r.error();
+}
+
+GoASTExpr *
+GoParser::TypeAssertion(GoASTExpr *e)
+{
+    Rule r("TypeAssertion", this);
+    if (match(GoLexer::OP_DOT) && match(GoLexer::OP_LPAREN))
+    {
+        if (auto *t = Type())
+        {
+            if (!mustMatch(GoLexer::OP_RPAREN))
+                return nullptr;
+            return new GoASTTypeAssertExpr(e, t);
+        }
+        return syntaxerror();
+    }
+    return r.error();
+}
+
+GoASTExpr *
+GoParser::Arguments(GoASTExpr *e)
+{
+    if (match(GoLexer::OP_LPAREN))
+    {
+        std::unique_ptr<GoASTCallExpr> call(new GoASTCallExpr(false));
+        GoASTExpr *arg;
+        // ( ExpressionList | Type [ "," ExpressionList ] )
+        for ((arg = Expression()) || (arg = Type()); arg; arg = MoreExpressionList())
+        {
+            call->AddArgs(arg);
+        }
+        if (match(GoLexer::OP_DOTS))
+            call->SetEllipsis(true);
+
+        // Eat trailing comma
+        match(GoLexer::OP_COMMA);
+
+        if (!mustMatch(GoLexer::OP_RPAREN))
+            return nullptr;
+        call->SetFun(e);
+        return call.release();
+    }
+    return nullptr;
+}
+
+GoASTExpr *
+GoParser::Conversion()
+{
+    Rule r("Conversion", this);
+    if (GoASTExpr *t = Type2())
+    {
+        if (match(GoLexer::OP_LPAREN))
+        {
+            GoASTExpr *v = Expression();
+            if (!v)
+                return syntaxerror();
+            match(GoLexer::OP_COMMA);
+            if (!mustMatch(GoLexer::OP_RPAREN))
+                return r.error();
+            GoASTCallExpr *call = new GoASTCallExpr(false);
+            call->SetFun(t);
+            call->AddArgs(v);
+            return call;
+        }
+    }
+    return r.error();
+}
+
+GoASTExpr *
+GoParser::Type2()
+{
+    switch (peek())
+    {
+        case GoLexer::OP_LBRACK:
+            return ArrayOrSliceType(false);
+        case GoLexer::KEYWORD_STRUCT:
+            return StructType();
+        case GoLexer::KEYWORD_FUNC:
+            return FunctionType();
+        case GoLexer::KEYWORD_INTERFACE:
+            return InterfaceType();
+        case GoLexer::KEYWORD_MAP:
+            return MapType();
+        case GoLexer::KEYWORD_CHAN:
+            return ChanType2();
+        default:
+            return nullptr;
+    }
+}
+
+GoASTExpr *
+GoParser::ArrayOrSliceType(bool allowEllipsis)
+{
+    Rule r("ArrayType", this);
+    if (match(GoLexer::OP_LBRACK))
+    {
+        std::unique_ptr<GoASTExpr> len;
+        if (allowEllipsis && match(GoLexer::OP_DOTS))
+        {
+            len.reset(new GoASTEllipsis(nullptr));
+        }
+        else
+        {
+            len.reset(Expression());
+        }
+
+        if (!match(GoLexer::OP_RBRACK))
+            return r.error();
+        GoASTExpr *elem = Type();
+        if (!elem)
+            return syntaxerror();
+        return new GoASTArrayType(len.release(), elem);
+    }
+    return r.error();
+}
+
+GoASTExpr *
+GoParser::StructType()
+{
+    if (!(match(GoLexer::KEYWORD_STRUCT) && mustMatch(GoLexer::OP_LBRACE)))
+        return nullptr;
+    std::unique_ptr<GoASTFieldList> fields(new GoASTFieldList);
+    while (auto *field = FieldDecl())
+        fields->AddList(field);
+    if (!mustMatch(GoLexer::OP_RBRACE))
+        return nullptr;
+    return new GoASTStructType(fields.release());
+}
+
+GoASTField *
+GoParser::FieldDecl()
+{
+    std::unique_ptr<GoASTField> f(new GoASTField);
+    GoASTExpr *t = FieldNamesAndType(f.get());
+    if (!t)
+        t = AnonymousFieldType();
+    if (!t)
+        return nullptr;
+
+    if (auto *tok = match(GoLexer::LIT_STRING))
+        f->SetTag(new GoASTBasicLit(*tok));
+    if (!Semicolon())
+        return syntaxerror();
+    return f.release();
+}
+
+GoASTExpr *
+GoParser::FieldNamesAndType(GoASTField *field)
+{
+    Rule r("FieldNames", this);
+    for (auto *id = Identifier(); id; id = MoreIdentifierList())
+        field->AddNames(id);
+    if (m_failed)
+        return nullptr;
+    GoASTExpr *t = Type();
+    if (t)
+        return t;
+    return r.error();
+}
+
+GoASTExpr *
+GoParser::AnonymousFieldType()
+{
+    bool pointer = match(GoLexer::OP_STAR);
+    GoASTExpr *t = Type();
+    if (!t)
+        return nullptr;
+    if (pointer)
+        return new GoASTStarExpr(t);
+    return t;
+}
+
+GoASTExpr *
+GoParser::FunctionType()
+{
+    if (!match(GoLexer::KEYWORD_FUNC))
+        return nullptr;
+    return Signature();
+}
+
+GoASTFuncType *
+GoParser::Signature()
+{
+    auto *params = Params();
+    if (!params)
+        return syntaxerror();
+    auto *result = Params();
+    if (!result)
+    {
+        if (auto *t = Type())
+        {
+            result = new GoASTFieldList;
+            auto *f = new GoASTField;
+            f->SetType(t);
+            result->AddList(f);
+        }
+    }
+    return new GoASTFuncType(params, result);
+}
+
+GoASTFieldList *
+GoParser::Params()
+{
+    if (!match(GoLexer::OP_LPAREN))
+        return nullptr;
+    std::unique_ptr<GoASTFieldList> l(new GoASTFieldList);
+    while (GoASTField *p = ParamDecl())
+    {
+        l->AddList(p);
+        if (!match(GoLexer::OP_COMMA))
+            break;
+    }
+    if (!mustMatch(GoLexer::OP_RPAREN))
+        return nullptr;
+    return l.release();
+}
+
+GoASTField *
+GoParser::ParamDecl()
+{
+    std::unique_ptr<GoASTField> field(new GoASTField);
+    GoASTIdent *id = Identifier();
+    if (id)
+    {
+        // Try `IdentifierList [ "..." ] Type`.
+        // If that fails, backtrack and try `[ "..." ] Type`.
+        Rule r("NamedParam", this);
+        for (; id; id = MoreIdentifierList())
+            field->AddNames(id);
+        GoASTExpr *t = ParamType();
+        if (t)
+        {
+            field->SetType(t);
+            return field.release();
+        }
+        field.reset(new GoASTField);
+        r.error();
+    }
+    GoASTExpr *t = ParamType();
+    if (t)
+    {
+        field->SetType(t);
+        return field.release();
+    }
+    return nullptr;
+}
+
+GoASTExpr *
+GoParser::ParamType()
+{
+    bool dots = match(GoLexer::OP_DOTS);
+    GoASTExpr *t = Type();
+    if (!dots)
+        return t;
+    if (!t)
+        return syntaxerror();
+    return new GoASTEllipsis(t);
+}
+
+GoASTExpr *
+GoParser::InterfaceType()
+{
+    if (!match(GoLexer::KEYWORD_INTERFACE) || !mustMatch(GoLexer::OP_LBRACE))
+        return nullptr;
+    std::unique_ptr<GoASTFieldList> methods(new GoASTFieldList);
+    while (true)
+    {
+        Rule r("MethodSpec", this);
+        // ( identifier Signature | TypeName ) ;
+        std::unique_ptr<GoASTIdent> id(Identifier());
+        if (!id)
+            break;
+        GoASTExpr *type = Signature();
+        if (!type)
+        {
+            r.error();
+            id.reset();
+            type = Name();
+        }
+        if (!Semicolon())
+            return syntaxerror();
+        auto *f = new GoASTField;
+        if (id)
+            f->AddNames(id.release());
+        f->SetType(type);
+        methods->AddList(f);
+    }
+    if (!mustMatch(GoLexer::OP_RBRACE))
+        return nullptr;
+    return new GoASTInterfaceType(methods.release());
+}
+
+GoASTExpr *
+GoParser::MapType()
+{
+    if (!(match(GoLexer::KEYWORD_MAP) && mustMatch(GoLexer::OP_LBRACK)))
+        return nullptr;
+    std::unique_ptr<GoASTExpr> key(Type());
+    if (!key)
+        return syntaxerror();
+    if (!mustMatch(GoLexer::OP_RBRACK))
+        return nullptr;
+    auto *elem = Type();
+    if (!elem)
+        return syntaxerror();
+    return new GoASTMapType(key.release(), elem);
+}
+
+GoASTExpr *
+GoParser::ChanType()
+{
+    Rule r("chan", this);
+    if (match(GoLexer::OP_LT_MINUS))
+    {
+        if (match(GoLexer::KEYWORD_CHAN))
+        {
+            auto *elem = Type();
+            if (!elem)
+                return syntaxerror();
+            return new GoASTChanType(GoASTNode::eChanRecv, elem);
+        }
+        return r.error();
+    }
+    return ChanType2();
+}
+
+GoASTExpr *
+GoParser::ChanType2()
+{
+    if (!match(GoLexer::KEYWORD_CHAN))
+        return nullptr;
+    auto dir = GoASTNode::eChanBidir;
+    if (match(GoLexer::OP_LT_MINUS))
+        dir = GoASTNode::eChanSend;
+    auto *elem = Type();
+    if (!elem)
+        return syntaxerror();
+    return new GoASTChanType(dir, elem);
+}
+
+GoASTExpr *
+GoParser::Type()
+{
+    if (GoASTExpr *t = Type2())
+        return t;
+    if (GoASTExpr *t = Name())
+        return t;
+    if (GoASTExpr *t = ChanType())
+        return t;
+    if (match(GoLexer::OP_STAR))
+    {
+        GoASTExpr *t = Type();
+        if (!t)
+            return syntaxerror();
+        return new GoASTStarExpr(t);
+    }
+    if (match(GoLexer::OP_LPAREN))
+    {
+        std::unique_ptr<GoASTExpr> t(Type());
+        if (!t || !match(GoLexer::OP_RPAREN))
+            return syntaxerror();
+        return t.release();
+    }
+    return nullptr;
+}
+
+bool
+GoParser::Semicolon()
+{
+    if (match(GoLexer::OP_SEMICOLON))
+        return true;
+    switch (peek())
+    {
+        case GoLexer::OP_RPAREN:
+        case GoLexer::OP_RBRACE:
+        case GoLexer::TOK_EOF:
+            return true;
+        default:
+            return false;
+    }
+}
+
+GoASTExpr *
+GoParser::Name()
+{
+    if (auto *id = Identifier())
+    {
+        if (GoASTExpr *qual = QualifiedIdent(id))
+            return qual;
+        return id;
+    }
+    return nullptr;
+}
+
+GoASTExpr *
+GoParser::QualifiedIdent(lldb_private::GoASTIdent *p)
+{
+    Rule r("QualifiedIdent", this);
+    llvm::SmallString<32> path(p->GetName().m_value);
+    GoLexer::Token *next;
+    bool have_slashes = false;
+    // LLDB extension: support full/package/path.name
+    while (match(GoLexer::OP_SLASH) && (next = match(GoLexer::TOK_IDENTIFIER)))
+    {
+        have_slashes = true;
+        path.append("/");
+        path.append(next->m_value);
+    }
+    if (match(GoLexer::OP_DOT))
+    {
+        auto *name = Identifier();
+        if (name)
+        {
+            if (have_slashes)
+            {
+                p->SetName(GoLexer::Token(GoLexer::TOK_IDENTIFIER, CopyString(path)));
+            }
+            return new GoASTSelectorExpr(p, name);
+        }
+    }
+    return r.error();
+}
+
+llvm::StringRef
+GoParser::CopyString(llvm::StringRef s)
+{
+    return m_strings.insert(std::make_pair(s, 'x')).first->getKey();
+}
+
+void
+GoParser::GetError(Error &error)
+{
+    llvm::StringRef want;
+    if (m_failed)
+        want = m_last_tok == GoLexer::TOK_INVALID ? DescribeToken(m_last_tok) : m_last;
+    else
+        want = m_error;
+    size_t len = m_lexer.BytesRemaining();
+    if (len > 10)
+        len = 10;
+    llvm::StringRef got;
+    if (len == 0)
+        got = "<eof>";
+    else
+        got = m_lexer.GetString(len);
+    error.SetErrorStringWithFormat("Syntax error: expected %s before '%s'.", want.str().c_str(), got.str().c_str());
+}

Added: lldb/trunk/source/Plugins/ExpressionParser/Go/GoParser.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Go/GoParser.h?rev=251820&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Go/GoParser.h (added)
+++ lldb/trunk/source/Plugins/ExpressionParser/Go/GoParser.h Mon Nov  2 13:30:40 2015
@@ -0,0 +1,165 @@
+//===-- GoParser.h -----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GoParser_h
+#define liblldb_GoParser_h
+
+#include "lldb/lldb-private.h"
+#include "Plugins/ExpressionParser/Go/GoAST.h"
+#include "Plugins/ExpressionParser/Go/GoLexer.h"
+
+namespace lldb_private
+{
+class GoParser
+{
+  public:
+    explicit GoParser(const char *src);
+
+    GoASTStmt *Statement();
+
+    GoASTStmt *GoStmt();
+    GoASTStmt *ReturnStmt();
+    GoASTStmt *BranchStmt();
+    GoASTStmt *EmptyStmt();
+    GoASTStmt *ExpressionStmt(GoASTExpr *e);
+    GoASTStmt *IncDecStmt(GoASTExpr *e);
+    GoASTStmt *Assignment(GoASTExpr *e);
+    GoASTBlockStmt *Block();
+
+    GoASTExpr *MoreExpressionList();  // ["," Expression]
+    GoASTIdent *MoreIdentifierList(); // ["," Identifier]
+
+    GoASTExpr *Expression();
+    GoASTExpr *UnaryExpr();
+    GoASTExpr *OrExpr();
+    GoASTExpr *AndExpr();
+    GoASTExpr *RelExpr();
+    GoASTExpr *AddExpr();
+    GoASTExpr *MulExpr();
+    GoASTExpr *PrimaryExpr();
+    GoASTExpr *Operand();
+    GoASTExpr *Conversion();
+
+    GoASTExpr *Selector(GoASTExpr *e);
+    GoASTExpr *IndexOrSlice(GoASTExpr *e);
+    GoASTExpr *TypeAssertion(GoASTExpr *e);
+    GoASTExpr *Arguments(GoASTExpr *e);
+
+    GoASTExpr *Type();
+    GoASTExpr *Type2();
+    GoASTExpr *ArrayOrSliceType(bool allowEllipsis);
+    GoASTExpr *StructType();
+    GoASTExpr *FunctionType();
+    GoASTExpr *InterfaceType();
+    GoASTExpr *MapType();
+    GoASTExpr *ChanType();
+    GoASTExpr *ChanType2();
+
+    GoASTExpr *Name();
+    GoASTExpr *QualifiedIdent(GoASTIdent *p);
+    GoASTIdent *Identifier();
+
+    GoASTField *FieldDecl();
+    GoASTExpr *AnonymousFieldType();
+    GoASTExpr *FieldNamesAndType(GoASTField *f);
+
+    GoASTFieldList *Params();
+    GoASTField *ParamDecl();
+    GoASTExpr *ParamType();
+    GoASTFuncType *Signature();
+    GoASTExpr *CompositeLit();
+    GoASTExpr *FunctionLit();
+    GoASTExpr *Element();
+    GoASTCompositeLit *LiteralValue();
+
+    bool
+    Failed() const
+    {
+        return m_failed;
+    }
+    bool
+    AtEOF() const
+    {
+        return m_lexer.BytesRemaining() == 0 && m_pos == m_tokens.size();
+    }
+
+    void GetError(Error &error);
+
+  private:
+    class Rule;
+    friend class Rule;
+
+    std::nullptr_t
+    syntaxerror()
+    {
+        m_failed = true;
+        return nullptr;
+    }
+    GoLexer::Token &
+    next()
+    {
+        if (m_pos >= m_tokens.size())
+        {
+            if (m_pos != 0 &&
+                (m_tokens.back().m_type == GoLexer::TOK_EOF || m_tokens.back().m_type == GoLexer::TOK_INVALID))
+                return m_tokens.back();
+            m_pos = m_tokens.size();
+            m_tokens.push_back(m_lexer.Lex());
+        }
+        return m_tokens[m_pos++];
+    }
+    GoLexer::TokenType
+    peek()
+    {
+        GoLexer::Token &tok = next();
+        --m_pos;
+        return tok.m_type;
+    }
+    GoLexer::Token *
+    match(GoLexer::TokenType t)
+    {
+        GoLexer::Token &tok = next();
+        if (tok.m_type == t)
+            return &tok;
+        --m_pos;
+        m_last_tok = t;
+        return nullptr;
+    }
+    GoLexer::Token *
+    mustMatch(GoLexer::TokenType t)
+    {
+        GoLexer::Token *tok = match(t);
+        if (tok)
+            return tok;
+        return syntaxerror();
+    }
+    bool Semicolon();
+
+    GoASTStmt *
+    FinishStmt(GoASTStmt *s)
+    {
+        if (!Semicolon())
+            m_failed = true;
+        return s;
+    }
+
+    llvm::StringRef CopyString(llvm::StringRef s);
+
+    GoLexer m_lexer;
+    std::vector<GoLexer::Token> m_tokens;
+    size_t m_pos;
+    llvm::StringRef m_error;
+    llvm::StringRef m_last;
+    GoLexer::TokenType m_last_tok;
+    llvm::StringMap<uint8_t> m_strings;
+    bool m_failed;
+};
+}
+
+#endif

Added: lldb/trunk/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp?rev=251820&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp (added)
+++ lldb/trunk/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp Mon Nov  2 13:30:40 2015
@@ -0,0 +1,735 @@
+//===-- GoUserExpression.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <cstdlib>
+#include <string>
+#include <map>
+#include <vector>
+
+#include "GoUserExpression.h"
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataEncoder.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Core/ValueObjectRegister.h"
+#include "lldb/Expression/ExpressionVariable.h"
+#include "lldb/Symbol/TypeList.h"
+#include "lldb/Symbol/GoASTContext.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanCallUserExpression.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringMap.h"
+
+#include "Plugins/ExpressionParser/Go/GoAST.h"
+#include "Plugins/ExpressionParser/Go/GoParser.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+class GoUserExpression::GoInterpreter
+{
+  public:
+    GoInterpreter(ExecutionContext &exe_ctx, const char *expr)
+        : m_exe_ctx(exe_ctx), m_frame(exe_ctx.GetFrameSP()), m_parser(expr)
+    {
+        if (m_frame)
+        {
+            const SymbolContext &ctx = m_frame->GetSymbolContext(eSymbolContextFunction);
+            ConstString fname = ctx.GetFunctionName();
+            if (fname.GetLength() > 0)
+            {
+                size_t dot = fname.GetStringRef().find('.');
+                if (dot != llvm::StringRef::npos)
+                    m_package = llvm::StringRef(fname.AsCString(), dot);
+            }
+        }
+    }
+
+    void
+    set_use_dynamic(DynamicValueType use_dynamic)
+    {
+        m_use_dynamic = use_dynamic;
+    }
+
+    bool Parse();
+    lldb::ValueObjectSP Evaluate(ExecutionContext &exe_ctx);
+    lldb::ValueObjectSP EvaluateStatement(const GoASTStmt *s);
+    lldb::ValueObjectSP EvaluateExpr(const GoASTExpr *e);
+
+    ValueObjectSP
+    VisitBadExpr(const GoASTBadExpr *e)
+    {
+        m_parser.GetError(m_error);
+        return nullptr;
+    }
+    ValueObjectSP VisitParenExpr(const GoASTParenExpr *e);
+    ValueObjectSP VisitIdent(const GoASTIdent *e);
+    ValueObjectSP VisitStarExpr(const GoASTStarExpr *e);
+    ValueObjectSP VisitSelectorExpr(const GoASTSelectorExpr *e);
+    ValueObjectSP VisitBasicLit(const GoASTBasicLit *e);
+    ValueObjectSP VisitIndexExpr(const GoASTIndexExpr *e);
+    ValueObjectSP VisitUnaryExpr(const GoASTUnaryExpr *e);
+    ValueObjectSP VisitCallExpr(const GoASTCallExpr *e);
+    ValueObjectSP
+    VisitTypeAssertExpr(const GoASTTypeAssertExpr *e)
+    {
+        return NotImplemented(e);
+    }
+    ValueObjectSP
+    VisitBinaryExpr(const GoASTBinaryExpr *e)
+    {
+        return NotImplemented(e);
+    }
+    ValueObjectSP
+    VisitArrayType(const GoASTArrayType *e)
+    {
+        return NotImplemented(e);
+    }
+    ValueObjectSP
+    VisitChanType(const GoASTChanType *e)
+    {
+        return NotImplemented(e);
+    }
+    ValueObjectSP
+    VisitCompositeLit(const GoASTCompositeLit *e)
+    {
+        return NotImplemented(e);
+    }
+    ValueObjectSP
+    VisitEllipsis(const GoASTEllipsis *e)
+    {
+        return NotImplemented(e);
+    }
+    ValueObjectSP
+    VisitFuncType(const GoASTFuncType *e)
+    {
+        return NotImplemented(e);
+    }
+    ValueObjectSP
+    VisitFuncLit(const GoASTFuncLit *e)
+    {
+        return NotImplemented(e);
+    }
+    ValueObjectSP
+    VisitInterfaceType(const GoASTInterfaceType *e)
+    {
+        return NotImplemented(e);
+    }
+    ValueObjectSP
+    VisitKeyValueExpr(const GoASTKeyValueExpr *e)
+    {
+        return NotImplemented(e);
+    }
+    ValueObjectSP
+    VisitMapType(const GoASTMapType *e)
+    {
+        return NotImplemented(e);
+    }
+    ValueObjectSP
+    VisitSliceExpr(const GoASTSliceExpr *e)
+    {
+        return NotImplemented(e);
+    }
+    ValueObjectSP
+    VisitStructType(const GoASTStructType *e)
+    {
+        return NotImplemented(e);
+    }
+
+    CompilerType EvaluateType(const GoASTExpr *e);
+
+    Error &
+    error()
+    {
+        return m_error;
+    }
+
+  private:
+    std::nullptr_t
+    NotImplemented(const GoASTExpr *e)
+    {
+        m_error.SetErrorStringWithFormat("%s node not implemented", e->GetKindName());
+        return nullptr;
+    }
+
+    ExecutionContext m_exe_ctx;
+    lldb::StackFrameSP m_frame;
+    GoParser m_parser;
+    DynamicValueType m_use_dynamic;
+    Error m_error;
+    llvm::StringRef m_package;
+    std::vector<std::unique_ptr<GoASTStmt>> m_statements;
+};
+
+VariableSP
+FindGlobalVariable(TargetSP target, llvm::Twine name)
+{
+    ConstString fullname(name.str());
+    VariableList variable_list;
+    const bool append = true;
+    if (!target)
+    {
+        return nullptr;
+    }
+    const uint32_t match_count = target->GetImages().FindGlobalVariables(fullname, append, 1, variable_list);
+    if (match_count == 1)
+    {
+        return variable_list.GetVariableAtIndex(0);
+    }
+    return nullptr;
+}
+
+CompilerType
+LookupType(TargetSP target, ConstString name)
+{
+    if (!target)
+        return CompilerType();
+    SymbolContext sc;
+    TypeList type_list;
+    uint32_t num_matches = target->GetImages().FindTypes(sc, name, false, 2, type_list);
+    if (num_matches > 0)
+    {
+        return type_list.GetTypeAtIndex(0)->GetFullCompilerType();
+    }
+    return CompilerType();
+}
+GoUserExpression::GoUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix,
+                                   lldb::LanguageType language, ResultType desired_type)
+    : UserExpression(exe_scope, expr, expr_prefix, language, desired_type)
+{
+}
+
+bool
+GoUserExpression::Parse(Stream &error_stream, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy,
+                        bool keep_result_in_memory, bool generate_debug_info)
+{
+    InstallContext(exe_ctx);
+    m_interpreter.reset(new GoInterpreter(exe_ctx, GetUserText()));
+    if (m_interpreter->Parse())
+        return true;
+    const char *error_cstr = m_interpreter->error().AsCString();
+    if (error_cstr && error_cstr[0])
+        error_stream.Printf("error: %s\n", error_cstr);
+    else
+        error_stream.Printf("error: expression can't be interpreted or run\n");
+    return false;
+}
+
+lldb::ExpressionResults
+GoUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options,
+                          lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result)
+{
+    Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
+
+    lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
+    lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
+
+    Process *process = exe_ctx.GetProcessPtr();
+    Target *target = exe_ctx.GetTargetPtr();
+
+    if (target == nullptr || process == nullptr || process->GetState() != lldb::eStateStopped)
+    {
+        if (execution_policy == eExecutionPolicyAlways)
+        {
+            if (log)
+                log->Printf("== [GoUserExpression::Evaluate] Expression may not run, but is not constant ==");
+
+            error_stream.Printf("expression needed to run but couldn't");
+
+            return execution_results;
+        }
+    }
+
+    m_interpreter->set_use_dynamic(options.GetUseDynamic());
+    ValueObjectSP result_val_sp = m_interpreter->Evaluate(exe_ctx);
+    Error err = m_interpreter->error();
+    m_interpreter.reset();
+
+    if (!result_val_sp)
+    {
+        const char *error_cstr = err.AsCString();
+        if (error_cstr && error_cstr[0])
+            error_stream.Printf("error: %s\n", error_cstr);
+        else
+            error_stream.Printf("error: expression can't be interpreted or run\n");
+        return lldb::eExpressionDiscarded;
+    }
+    result.reset(new ExpressionVariable(ExpressionVariable::eKindGo));
+    result->m_live_sp = result->m_frozen_sp = result_val_sp;
+    result->m_flags |= ExpressionVariable::EVIsProgramReference;
+    PersistentExpressionState *pv = target->GetPersistentExpressionStateForLanguage(eLanguageTypeGo);
+    if (pv != nullptr)
+    {
+        result->SetName(pv->GetNextPersistentVariableName());
+        pv->AddVariable(result);
+    }
+    return lldb::eExpressionCompleted;
+}
+
+bool
+GoUserExpression::GoInterpreter::Parse()
+{
+    for (std::unique_ptr<GoASTStmt> stmt(m_parser.Statement()); stmt; stmt.reset(m_parser.Statement()))
+    {
+        if (m_parser.Failed())
+            break;
+        m_statements.emplace_back(std::move(stmt));
+    }
+    if (m_parser.Failed() || !m_parser.AtEOF())
+        m_parser.GetError(m_error);
+
+    return m_error.Success();
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::Evaluate(ExecutionContext &exe_ctx)
+{
+    m_exe_ctx = exe_ctx;
+    ValueObjectSP result;
+    for (const std::unique_ptr<GoASTStmt> &stmt : m_statements)
+    {
+        result = EvaluateStatement(stmt.get());
+        if (m_error.Fail())
+            return nullptr;
+    }
+    return result;
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::EvaluateStatement(const lldb_private::GoASTStmt *stmt)
+{
+    ValueObjectSP result;
+    switch (stmt->GetKind())
+    {
+        case GoASTNode::eBlockStmt:
+        {
+            const GoASTBlockStmt *block = llvm::cast<GoASTBlockStmt>(stmt);
+            for (size_t i = 0; i < block->NumList(); ++i)
+                result = EvaluateStatement(block->GetList(i));
+            break;
+        }
+        case GoASTNode::eBadStmt:
+            m_parser.GetError(m_error);
+            break;
+        case GoASTNode::eExprStmt:
+        {
+            const GoASTExprStmt *expr = llvm::cast<GoASTExprStmt>(stmt);
+            return EvaluateExpr(expr->GetX());
+        }
+        default:
+            m_error.SetErrorStringWithFormat("%s node not supported", stmt->GetKindName());
+    }
+    return result;
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::EvaluateExpr(const lldb_private::GoASTExpr *e)
+{
+    if (e)
+        return e->Visit<ValueObjectSP>(this);
+    return ValueObjectSP();
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitParenExpr(const lldb_private::GoASTParenExpr *e)
+{
+    return EvaluateExpr(e->GetX());
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitIdent(const GoASTIdent *e)
+{
+    ValueObjectSP val;
+    if (m_frame)
+    {
+        VariableSP var_sp;
+        std::string varname = e->GetName().m_value.str();
+        if (varname.size() > 1 && varname[0] == '$')
+        {
+            RegisterContextSP reg_ctx_sp = m_frame->GetRegisterContext();
+            const RegisterInfo *reg = reg_ctx_sp->GetRegisterInfoByName(varname.c_str() + 1);
+            if (reg)
+            {
+                std::string type;
+                switch (reg->encoding)
+                {
+                    case lldb::eEncodingSint:
+                        type.append("int");
+                        break;
+                    case lldb::eEncodingUint:
+                        type.append("uint");
+                        break;
+                    case lldb::eEncodingIEEE754:
+                        type.append("float");
+                        break;
+                    default:
+                        m_error.SetErrorString("Invaild register encoding");
+                        return nullptr;
+                }
+                switch (reg->byte_size)
+                {
+                    case 8:
+                        type.append("64");
+                        break;
+                    case 4:
+                        type.append("32");
+                        break;
+                    case 2:
+                        type.append("16");
+                        break;
+                    case 1:
+                        type.append("8");
+                        break;
+                    default:
+                        m_error.SetErrorString("Invaild register size");
+                        return nullptr;
+                }
+                ValueObjectSP regVal =
+                    ValueObjectRegister::Create(m_frame.get(), reg_ctx_sp, reg->kinds[eRegisterKindLLDB]);
+                CompilerType goType = LookupType(m_frame->CalculateTarget(), ConstString(type));
+                if (regVal)
+                {
+                    regVal = regVal->Cast(goType);
+                    return regVal;
+                }
+            }
+            m_error.SetErrorString("Invaild register name");
+            return nullptr;
+        }
+        VariableListSP var_list_sp(m_frame->GetInScopeVariableList(false));
+        if (var_list_sp)
+        {
+            var_sp = var_list_sp->FindVariable(ConstString(varname));
+            if (var_sp)
+                val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic);
+            else
+            {
+                // When a variable is on the heap instead of the stack, go records a variable
+                // '&x' instead of 'x'.
+                var_sp = var_list_sp->FindVariable(ConstString("&" + varname));
+                if (var_sp)
+                {
+                    val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic);
+                    if (val)
+                        val = val->Dereference(m_error);
+                    if (m_error.Fail())
+                        return nullptr;
+                }
+            }
+        }
+        if (!val)
+        {
+            m_error.Clear();
+            TargetSP target = m_frame->CalculateTarget();
+            if (!target)
+            {
+                m_error.SetErrorString("No target");
+                return nullptr;
+            }
+            var_sp = FindGlobalVariable(target, m_package + "." + e->GetName().m_value);
+            if (var_sp)
+                return m_frame->TrackGlobalVariable(var_sp, m_use_dynamic);
+        }
+    }
+    if (!val)
+        m_error.SetErrorStringWithFormat("Unknown variable %s", e->GetName().m_value.str().c_str());
+    return val;
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitStarExpr(const GoASTStarExpr *e)
+{
+    ValueObjectSP target = EvaluateExpr(e->GetX());
+    if (!target)
+        return nullptr;
+    return target->Dereference(m_error);
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitSelectorExpr(const lldb_private::GoASTSelectorExpr *e)
+{
+    ValueObjectSP target = EvaluateExpr(e->GetX());
+    if (target)
+    {
+        if (target->GetCompilerType().IsPointerType())
+        {
+            target = target->Dereference(m_error);
+            if (m_error.Fail())
+                return nullptr;
+        }
+        ConstString field(e->GetSel()->GetName().m_value);
+        ValueObjectSP result = target->GetChildMemberWithName(field, true);
+        if (!result)
+            m_error.SetErrorStringWithFormat("Unknown child %s", field.AsCString());
+        return result;
+    }
+    if (const GoASTIdent *package = llvm::dyn_cast<GoASTIdent>(e->GetX()))
+    {
+        if (VariableSP global = FindGlobalVariable(m_exe_ctx.GetTargetSP(),
+                                                   package->GetName().m_value + "." + e->GetSel()->GetName().m_value))
+        {
+            if (m_frame)
+            {
+                m_error.Clear();
+                return m_frame->GetValueObjectForFrameVariable(global, m_use_dynamic);
+            }
+        }
+    }
+    if (const GoASTBasicLit *packageLit = llvm::dyn_cast<GoASTBasicLit>(e->GetX()))
+    {
+        if (packageLit->GetValue().m_type == GoLexer::LIT_STRING)
+        {
+            std::string value = packageLit->GetValue().m_value.str();
+            value = value.substr(1, value.size() - 2);
+            if (VariableSP global =
+                    FindGlobalVariable(m_exe_ctx.GetTargetSP(), value + "." + e->GetSel()->GetName().m_value))
+            {
+                if (m_frame)
+                {
+                    m_error.Clear();
+                    return m_frame->TrackGlobalVariable(global, m_use_dynamic);
+                }
+            }
+        }
+    }
+    // EvaluateExpr should have already set m_error.
+    return target;
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitBasicLit(const lldb_private::GoASTBasicLit *e)
+{
+    std::string value = e->GetValue().m_value.str();
+    if (e->GetValue().m_type != GoLexer::LIT_INTEGER)
+    {
+        m_error.SetErrorStringWithFormat("Unsupported literal %s", value.c_str());
+        return nullptr;
+    }
+    errno = 0;
+    int64_t intvalue = strtol(value.c_str(), NULL, 0);
+    if (errno != 0)
+    {
+        m_error.SetErrorToErrno();
+        return nullptr;
+    }
+    DataBufferSP buf(new DataBufferHeap(sizeof(intvalue), 0));
+    TargetSP target = m_exe_ctx.GetTargetSP();
+    if (!target)
+    {
+        m_error.SetErrorString("No target");
+        return nullptr;
+    }
+    ByteOrder order = target->GetArchitecture().GetByteOrder();
+    uint8_t addr_size = target->GetArchitecture().GetAddressByteSize();
+    DataEncoder enc(buf, order, addr_size);
+    enc.PutU64(0, static_cast<uint64_t>(intvalue));
+    DataExtractor data(buf, order, addr_size);
+
+    CompilerType type = LookupType(target, ConstString("int64"));
+    return ValueObject::CreateValueObjectFromData(nullptr, data, m_exe_ctx, type);
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitIndexExpr(const lldb_private::GoASTIndexExpr *e)
+{
+    ValueObjectSP target = EvaluateExpr(e->GetX());
+    if (!target)
+        return nullptr;
+    ValueObjectSP index = EvaluateExpr(e->GetIndex());
+    if (!index)
+        return nullptr;
+    bool is_signed;
+    if (!index->GetCompilerType().IsIntegerType(is_signed))
+    {
+        m_error.SetErrorString("Unsupported index");
+        return nullptr;
+    }
+    size_t idx;
+    if (is_signed)
+        idx = index->GetValueAsSigned(0);
+    else
+        idx = index->GetValueAsUnsigned(0);
+    if (GoASTContext::IsGoSlice(target->GetCompilerType()))
+    {
+        target = target->GetStaticValue();
+        ValueObjectSP cap = target->GetChildMemberWithName(ConstString("cap"), true);
+        if (cap)
+        {
+            uint64_t capval = cap->GetValueAsUnsigned(0);
+            if (idx >= capval)
+            {
+                m_error.SetErrorStringWithFormat("Invalid index %" PRIu64 " , cap = %" PRIu64, uint64_t(idx), capval);
+                return nullptr;
+            }
+        }
+        target = target->GetChildMemberWithName(ConstString("array"), true);
+        if (target && m_use_dynamic != eNoDynamicValues)
+        {
+            ValueObjectSP dynamic = target->GetDynamicValue(m_use_dynamic);
+            if (dynamic)
+                target = dynamic;
+        }
+        if (!target)
+            return nullptr;
+        return target->GetSyntheticArrayMember(idx, true);
+    }
+    return target->GetChildAtIndex(idx, true);
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitUnaryExpr(const GoASTUnaryExpr *e)
+{
+    ValueObjectSP x = EvaluateExpr(e->GetX());
+    if (!x)
+        return nullptr;
+    switch (e->GetOp())
+    {
+        case GoLexer::OP_AMP:
+        {
+            CompilerType type = x->GetCompilerType().GetPointerType();
+            uint64_t address = x->GetAddressOf();
+            return ValueObject::CreateValueObjectFromAddress(nullptr, address, m_exe_ctx, type);
+        }
+        case GoLexer::OP_PLUS:
+            return x;
+        default:
+            m_error.SetErrorStringWithFormat("Operator %s not supported",
+                                             GoLexer::LookupToken(e->GetOp()).str().c_str());
+            return nullptr;
+    }
+}
+
+CompilerType
+GoUserExpression::GoInterpreter::EvaluateType(const GoASTExpr *e)
+{
+    TargetSP target = m_exe_ctx.GetTargetSP();
+    if (auto *id = llvm::dyn_cast<GoASTIdent>(e))
+    {
+        CompilerType result = LookupType(target, ConstString(id->GetName().m_value));
+        if (result.IsValid())
+            return result;
+        std::string fullname = (m_package + "." + id->GetName().m_value).str();
+        result = LookupType(target, ConstString(fullname));
+        if (!result)
+            m_error.SetErrorStringWithFormat("Unknown type %s", fullname.c_str());
+        return result;
+    }
+    if (auto *sel = llvm::dyn_cast<GoASTSelectorExpr>(e))
+    {
+        std::string package;
+        if (auto *pkg_node = llvm::dyn_cast<GoASTIdent>(sel->GetX()))
+        {
+            package = pkg_node->GetName().m_value.str();
+        }
+        else if (auto *str_node = llvm::dyn_cast<GoASTBasicLit>(sel->GetX()))
+        {
+            if (str_node->GetValue().m_type == GoLexer::LIT_STRING)
+            {
+                package = str_node->GetValue().m_value.substr(1).str();
+                package.resize(package.length() - 1);
+            }
+        }
+        if (package.empty())
+        {
+            m_error.SetErrorStringWithFormat("Invalid %s in type expression", sel->GetX()->GetKindName());
+            return CompilerType();
+        }
+        std::string fullname = (package + "." + sel->GetSel()->GetName().m_value).str();
+        CompilerType result = LookupType(target, ConstString(fullname));
+        if (!result)
+            m_error.SetErrorStringWithFormat("Unknown type %s", fullname.c_str());
+        return result;
+    }
+    if (auto *star = llvm::dyn_cast<GoASTStarExpr>(e))
+    {
+        CompilerType elem = EvaluateType(star->GetX());
+        return elem.GetPointerType();
+    }
+    if (auto *paren = llvm::dyn_cast<GoASTParenExpr>(e))
+        return EvaluateType(paren->GetX());
+    if (auto *array = llvm::dyn_cast<GoASTArrayType>(e))
+    {
+        CompilerType elem = EvaluateType(array->GetElt());
+    }
+
+    m_error.SetErrorStringWithFormat("Invalid %s in type expression", e->GetKindName());
+    return CompilerType();
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitCallExpr(const lldb_private::GoASTCallExpr *e)
+{
+    ValueObjectSP x = EvaluateExpr(e->GetFun());
+    if (x || e->NumArgs() != 1)
+    {
+        m_error.SetErrorStringWithFormat("Code execution not supported");
+        return nullptr;
+    }
+    m_error.Clear();
+    CompilerType type = EvaluateType(e->GetFun());
+    if (!type)
+    {
+        return nullptr;
+    }
+    ValueObjectSP value = EvaluateExpr(e->GetArgs(0));
+    if (!value)
+        return nullptr;
+    // TODO: Handle special conversions
+    return value->Cast(type);
+}
+
+GoPersistentExpressionState::GoPersistentExpressionState() : PersistentExpressionState(eKindGo)
+{
+}
+
+ConstString
+GoPersistentExpressionState::GetNextPersistentVariableName()
+{
+    char name_cstr[256];
+    // We can't use the same variable format as clang.
+    ::snprintf(name_cstr, sizeof(name_cstr), "$go%u", m_next_persistent_variable_id++);
+    ConstString name(name_cstr);
+    return name;
+}
+
+void
+GoPersistentExpressionState::RemovePersistentVariable(lldb::ExpressionVariableSP variable)
+{
+    RemoveVariable(variable);
+
+    const char *name = variable->GetName().AsCString();
+
+    if (*(name++) != '$')
+        return;
+    if (*(name++) != 'g')
+        return;
+    if (*(name++) != 'o')
+        return;
+
+    if (strtoul(name, NULL, 0) == m_next_persistent_variable_id - 1)
+        m_next_persistent_variable_id--;
+}

Added: lldb/trunk/source/Plugins/ExpressionParser/Go/GoUserExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Go/GoUserExpression.h?rev=251820&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Go/GoUserExpression.h (added)
+++ lldb/trunk/source/Plugins/ExpressionParser/Go/GoUserExpression.h Mon Nov  2 13:30:40 2015
@@ -0,0 +1,99 @@
+//===-- GoUserExpression.h -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GoUserExpression_h_
+#define liblldb_GoUserExpression_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+#include <map>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+#include "lldb/Expression/UserExpression.h"
+#include "lldb/Expression/ExpressionVariable.h"
+#include "lldb/Target/ExecutionContext.h"
+
+namespace lldb_private
+{
+class GoParser;
+
+class GoPersistentExpressionState : public PersistentExpressionState
+{
+  public:
+    GoPersistentExpressionState();
+
+    ConstString GetNextPersistentVariableName() override;
+
+    void RemovePersistentVariable(lldb::ExpressionVariableSP variable) override;
+
+    lldb::addr_t
+    LookupSymbol(const ConstString &name) override
+    {
+        return LLDB_INVALID_ADDRESS;
+    }
+
+    static bool
+    classof(const PersistentExpressionState *pv)
+    {
+        return pv->getKind() == PersistentExpressionState::eKindGo;
+    }
+
+  private:
+    uint32_t m_next_persistent_variable_id; ///< The counter used by GetNextResultName().
+};
+
+//----------------------------------------------------------------------
+/// @class GoUserExpression GoUserExpression.h "lldb/Expression/GoUserExpression.h"
+/// @brief Encapsulates a single expression for use with Go
+///
+/// LLDB uses expressions for various purposes, notably to call functions
+/// and as a backend for the expr command.  GoUserExpression encapsulates
+/// the objects needed to parse and interpret an expression.
+//----------------------------------------------------------------------
+class GoUserExpression : public UserExpression
+{
+  public:
+    GoUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix,
+                     lldb::LanguageType language, ResultType desired_type);
+
+    virtual bool Parse(Stream &error_stream, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy,
+                       bool keep_result_in_memory, bool generate_debug_info) override;
+
+    virtual lldb::ExpressionResults Execute(Stream &error_stream, ExecutionContext &exe_ctx,
+                                            const EvaluateExpressionOptions &options,
+                                            lldb::UserExpressionSP &shared_ptr_to_me,
+                                            lldb::ExpressionVariableSP &result) override;
+
+    bool
+    CanInterpret() override
+    {
+        return true;
+    }
+    bool
+    FinalizeJITExecution(Stream &error_stream, ExecutionContext &exe_ctx, lldb::ExpressionVariableSP &result,
+                         lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS,
+                         lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS) override
+    {
+        return true;
+    }
+
+  private:
+    class GoInterpreter;
+    std::unique_ptr<GoInterpreter> m_interpreter;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_GoUserExpression_h_

Added: lldb/trunk/source/Plugins/ExpressionParser/Go/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Go/Makefile?rev=251820&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Go/Makefile (added)
+++ lldb/trunk/source/Plugins/ExpressionParser/Go/Makefile Mon Nov  2 13:30:40 2015
@@ -0,0 +1,14 @@
+##===- source/Plugins/ExpressionParser/Clang ---------------*- Makefile -*-===##
+# 
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+# 
+##===----------------------------------------------------------------------===##
+
+LLDB_LEVEL := ../../../..
+LIBRARYNAME := lldbPluginExpressionParserGo
+BUILD_ARCHIVE = 1
+
+include $(LLDB_LEVEL)/Makefile

Added: lldb/trunk/source/Plugins/ExpressionParser/Go/gen_go_ast.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Go/gen_go_ast.py?rev=251820&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Go/gen_go_ast.py (added)
+++ lldb/trunk/source/Plugins/ExpressionParser/Go/gen_go_ast.py Mon Nov  2 13:30:40 2015
@@ -0,0 +1,356 @@
+import StringIO
+
+def addNodes():
+    addNode("ArrayType", "Expr", "len", "Expr", "elt", "Expr")
+    addNode("AssignStmt", "Stmt", "lhs", "[]Expr", "rhs", "[]Expr", "define", "bool")
+    addNode("BadDecl", "Decl")
+    addNode("BadExpr", "Expr")
+    addNode("BadStmt", "Stmt")
+    addNode("BasicLit", "Expr", "value", "Token")
+    addNode("BinaryExpr", "Expr", "x", "Expr", "y", "Expr", "op", "TokenType")
+    addNode("BlockStmt", "Stmt", "list", "[]Stmt")
+    addNode("Ident", "Expr", "name", "Token")
+    addNode("BranchStmt", "Stmt", "label", "Ident", "tok", "TokenType")
+    addNode("CallExpr", "Expr", "fun", "Expr", "args", "[]Expr", "ellipsis", "bool")
+    addNode("CaseClause", "Stmt", "list", "[]Expr", "body", "[]Stmt")
+    addNode("ChanType", "Expr", "dir", "ChanDir", "value", "Expr")
+    addNode("CommClause", "Stmt", "comm", "Stmt", "body", "[]Stmt")
+    addNode("CompositeLit", "Expr", "type", "Expr", "elts", "[]Expr")
+    addNode("DeclStmt", "Stmt", "decl", "Decl")
+    addNode("DeferStmt", "Stmt", "call", "CallExpr")
+    addNode("Ellipsis", "Expr", "elt", "Expr")
+    addNode("EmptyStmt", "Stmt")
+    addNode("ExprStmt", "Stmt", "x", "Expr")
+    addNode("Field", "Node", "names", "[]Ident", "type", "Expr", "tag", "BasicLit")
+    addNode("FieldList", "Node", "list", "[]Field")
+    addNode("ForStmt", "Stmt", "init", "Stmt", "cond", "Expr", "post", "Stmt", "body", "BlockStmt")
+    addNode("FuncType", "Expr", "params", "FieldList", "results", "FieldList")
+    addNode("FuncDecl", "Decl", "recv", "FieldList", "name", "Ident", "type", "FuncType", "body", "BlockStmt")
+    addNode("FuncLit", "Expr", "type", "FuncType", "body", "BlockStmt")
+    addNode("GenDecl", "Decl", "tok", "TokenType", "specs", "[]Spec")
+    addNode("GoStmt", "Stmt", "call", "CallExpr")
+    addNode("IfStmt", "Stmt", "init", "Stmt", "cond", "Expr", "body", "BlockStmt", "els", "Stmt")
+    addNode("ImportSpec", "Spec", "name", "Ident", "path", "BasicLit")
+    addNode("IncDecStmt", "Stmt", "x", "Expr", "tok", "TokenType")
+    addNode("IndexExpr", "Expr", "x", "Expr", "index", "Expr")
+    addNode("InterfaceType", "Expr", "methods", "FieldList")
+    addNode("KeyValueExpr", "Expr", "key", "Expr", "value", "Expr")
+    addNode("LabeledStmt", "Stmt", "label", "Ident", "stmt", "Stmt")
+    addNode("MapType", "Expr", "key", "Expr", "value", "Expr")
+    addNode("ParenExpr", "Expr", "x", "Expr")
+    addNode("RangeStmt", "Stmt", "key", "Expr", "value", "Expr", "define", "bool", "x", "Expr", "body", "BlockStmt")
+    addNode("ReturnStmt", "Stmt", "results", "[]Expr")
+    addNode("SelectStmt", "Stmt", "body", "BlockStmt")
+    addNode("SelectorExpr", "Expr", "x", "Expr", "sel", "Ident")
+    addNode("SendStmt", "Stmt", "chan", "Expr", "value", "Expr")
+    addNode("SliceExpr", "Expr", "x", "Expr", "low", "Expr", "high", "Expr", "max", "Expr", "slice3", "bool")
+    addNode("StarExpr", "Expr", "x", "Expr")
+    addNode("StructType", "Expr", "fields", "FieldList")
+    addNode("SwitchStmt", "Stmt", "init", "Stmt", "tag", "Expr", "body", "BlockStmt")
+    addNode("TypeAssertExpr", "Expr", "x", "Expr", "type", "Expr")
+    addNode("TypeSpec", "Spec", "name", "Ident", "type", "Expr")
+    addNode("TypeSwitchStmt", "Stmt", "init", "Stmt", "assign", "Stmt", "body", "BlockStmt")
+    addNode("UnaryExpr", "Expr", "op", "TokenType", "x", "Expr")
+    addNode("ValueSpec", "Spec", "names", "[]Ident", "type", "Expr", "values", "[]Expr")
+    addParent("Decl", "Node")
+    addParent("Expr", "Node")
+    addParent("Spec", "Node")
+    addParent("Stmt", "Node")
+
+
+class Member(object):
+    def __init__(self, name, typename):
+        self.title = name.title()
+        self.sname = name
+        self.mname = 'm_' + name
+        self.is_list = typename.startswith("[]")
+        self.is_value = isValueType(typename)
+        if self.is_value:
+            self.argtype = typename
+            self.mtype = typename
+        elif self.is_list:
+            self.argtype = 'GoAST' + typename[2:]
+            self.mtype = 'std::vector<std::unique_ptr<%s> >' % self.argtype
+        else:
+            self.argtype = 'GoAST' + typename
+            self.mtype = 'std::unique_ptr<%s>' % self.argtype
+            self.mname = self.mname + '_up'
+    
+
+kinds = {}
+parentClasses = StringIO.StringIO()
+childClasses = StringIO.StringIO()
+walker = StringIO.StringIO()
+
+def startClass(name, parent, out):
+    out.write("""
+class GoAST%s : public GoAST%s
+{
+  public:
+""" % (name, parent))
+
+def endClass(name, out):
+    out.write("""
+    %(name)s(const %(name)s &) = delete;
+    const %(name)s &operator=(const %(name)s &) = delete;
+};
+""" % {'name': 'GoAST' + name})
+
+def addNode(name, parent, *children):
+    startClass(name, parent, childClasses)
+    l = kinds.setdefault(parent, [])
+    l.append(name)
+    children = createMembers(name, children)
+    addConstructor(name, parent, children)
+    childClasses.write("""
+    const char *
+    GetKindName() const override
+    {
+        return "%(name)s";
+    }
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() == e%(name)s;
+    }
+    """ % {'name':name})
+    addChildren(name, children)
+    endClass(name, childClasses)
+
+def isValueType(typename):
+    if typename[0].islower():
+        return True
+    if typename[0].isupper():
+        return typename.startswith('Token') or typename == 'ChanDir'
+    return False
+
+
+def createMembers(name, children):
+    l = len(children)
+    if (l % 2) != 0:
+        raise Exception("Invalid children for %s: %s" % (name, children))
+    return [Member(children[i], children[i + 1]) for i in xrange(0, l, 2)]
+
+
+def addConstructor(name, parent, children):
+    for c in children:
+        if c.is_list:
+            children = [x for x in children if x.is_value]
+            break
+    childClasses.write('    ')
+    if len(children) == 1:
+        childClasses.write('explicit ')
+    childClasses.write('GoAST%s(' % name)
+    for i in xrange(len(children)):
+        if i > 0:
+            childClasses.write(', ')
+
+        c = children[i]
+        if c.is_value:
+            childClasses.write(c.argtype)
+            childClasses.write(' ')
+        else:
+            childClasses.write('%s *' % c.argtype)
+        childClasses.write(c.sname)
+    childClasses.write(') : GoAST%s(e%s)' % (parent, name))
+    for c in children:
+        childClasses.write(', ')
+        childClasses.write('%(mname)s(%(sname)s)' % c.__dict__)
+    childClasses.write(""" {}
+    ~GoAST%s() override = default;
+""" % name)
+
+    
+def addChildren(name, children):
+    if len(children) == 0:
+        return
+    walker.write("""
+    case e%(n)s:
+        {
+            GoAST%(n)s *n = llvm::cast<GoAST%(n)s>(this);
+            (void)n;""" % {'n':name})
+    for c in children:
+        if c.is_list:
+            childClasses.write("""
+    size_t
+    Num%(title)s() const
+    {
+        return %(mname)s.size();
+    }
+    const %(argtype)s *
+    Get%(title)s(int i) const
+    {
+        return %(mname)s[i].get();
+    }
+    void
+    Add%(title)s(%(argtype)s *%(sname)s)
+    {
+        %(mname)s.push_back(std::unique_ptr<%(argtype)s>(%(sname)s));
+    }
+""" % c.__dict__)
+            walker.write("""
+            for (auto& e : n->%s) { v(e.get()); }""" % c.mname)
+        else:
+            const = ''
+            get = ''
+            set = ''
+            t = c.argtype
+            if isValueType(t):
+                set = '%(mname)s = %(sname)s' % c.__dict__
+                t = t + ' '
+            else:
+                t = t + ' *'
+                const = 'const '
+                get = '.get()'
+                set = '%(mname)s.reset(%(sname)s)' % c.__dict__
+                walker.write("""
+            v(n->%s.get());""" % c.mname)
+            childClasses.write("""
+    %(const)s%(type)s
+    Get%(title)s() const
+    {
+        return %(mname)s%(get)s;
+    }
+    void
+    Set%(title)s(%(type)s%(sname)s)
+    {
+        %(set)s;
+    }
+""" % {'const':const, 'title': c.title, 'sname': c.sname, 'get': get, 'set': set, 'type': t, 'mname': c.mname})
+    childClasses.write('\n  private:\n    friend class GoASTNode;\n')
+    walker.write("""
+            return;
+        }""")
+    for c in children:
+        childClasses.write('    %s %s;\n' %(c.mtype, c.mname))
+    
+
+def addParent(name, parent):
+    startClass(name, parent, parentClasses)
+    l = kinds[name]
+    minName = l[0]
+    maxName = l[-1]
+    parentClasses.write("""    template <typename R, typename V> R Visit(V *v) const;
+
+    static bool
+    classof(const GoASTNode *n)
+    {
+        return n->GetKind() >= e%s && n->GetKind() <= e%s;
+    }
+
+  protected:
+    explicit GoAST%s(NodeKind kind) : GoASTNode(kind) { }
+  private:
+""" % (minName, maxName, name))
+    endClass(name, parentClasses)
+    
+addNodes()
+
+print """//===-- GoAST.h -------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// DO NOT EDIT.
+// Generated by gen_go_ast.py
+
+#ifndef liblldb_GoAST_h
+#define liblldb_GoAST_h
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+#include "llvm/Support/Casting.h"
+#include "Plugins/ExpressionParser/Go/GoLexer.h"
+
+namespace lldb_private
+{
+
+class GoASTNode
+{
+  public:
+    typedef GoLexer::TokenType TokenType;
+    typedef GoLexer::Token Token;
+    enum ChanDir
+    {
+        eChanBidir,
+        eChanSend,
+        eChanRecv,
+    };
+    enum NodeKind
+    {"""
+for l in kinds.itervalues():
+    for x in l:
+        print "        e%s," % x
+print """    };
+
+    virtual ~GoASTNode() = default;
+
+    NodeKind
+    GetKind() const
+    {
+        return m_kind;
+    }
+
+    virtual const char *GetKindName() const = 0;
+
+    template <typename V> void WalkChildren(V &v);
+
+  protected:
+    explicit GoASTNode(NodeKind kind) : m_kind(kind) { }
+
+  private:
+    const NodeKind m_kind;
+    
+    GoASTNode(const GoASTNode &) = delete;
+    const GoASTNode &operator=(const GoASTNode &) = delete;
+};
+"""
+
+
+print parentClasses.getvalue()
+print childClasses.getvalue()
+
+for k, l in kinds.iteritems():
+    if k == 'Node':
+        continue
+    print """
+template <typename R, typename V>
+R GoAST%s::Visit(V* v) const
+{
+    switch(GetKind())
+    {""" % k
+    for subtype in l:
+        print """    case e%(n)s:
+        return v->Visit%(n)s(llvm::cast<const GoAST%(n)s>(this));""" % {'n':subtype}
+
+    print """    default:
+        assert(false && "Invalid kind");
+    }
+}"""
+
+print """
+template <typename V>
+void GoASTNode::WalkChildren(V &v)
+{
+    switch (m_kind)
+    {
+"""
+print walker.getvalue()
+print"""
+        case eEmptyStmt:
+        case eBadDecl:
+        case eBadExpr:
+        case eBadStmt:
+          break;
+    }
+}
+
+}  // namespace lldb_private
+
+#endif
+"""

Modified: lldb/trunk/source/Symbol/GoASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/GoASTContext.cpp?rev=251820&r1=251819&r2=251820&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/GoASTContext.cpp (original)
+++ lldb/trunk/source/Symbol/GoASTContext.cpp Mon Nov  2 13:30:40 2015
@@ -24,6 +24,7 @@
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Target.h"
 
+#include "Plugins/ExpressionParser/Go/GoUserExpression.h"
 #include "Plugins/SymbolFile/DWARF/DWARFASTParserGo.h"
 
 using namespace lldb;
@@ -200,9 +201,7 @@ class GoStruct : public GoType
     };
 
     GoStruct(int kind, const ConstString &name, int64_t byte_size)
-        : GoType(kind, name)
-        , m_is_complete(false)
-        , m_byte_size(byte_size)
+        : GoType(kind == 0 ? KIND_STRUCT : kind, name), m_is_complete(false), m_byte_size(byte_size)
     {
     }
 
@@ -327,14 +326,20 @@ GoASTContext::CreateInstance (lldb::Lang
     if (language == eLanguageTypeGo)
     {
         ArchSpec arch;
+        std::shared_ptr<GoASTContext> go_ast_sp;
         if (module)
+        {
             arch = module->GetArchitecture();
+            go_ast_sp = std::shared_ptr<GoASTContext>(new GoASTContext);
+        }
         else if (target)
+        {
             arch = target->GetArchitecture();
+            go_ast_sp = std::shared_ptr<GoASTContextForExpr>(new GoASTContextForExpr(target->shared_from_this()));
+        }
 
         if (arch.IsValid())
         {
-            std::shared_ptr<GoASTContext> go_ast_sp(new GoASTContext);
             go_ast_sp->SetAddressByteSize(arch.GetAddressByteSize());
             return go_ast_sp;
         }
@@ -414,6 +419,10 @@ GoASTContext::IsAggregateType(lldb::opaq
         return false;
     if (kind == GoType::KIND_PTR)
         return false;
+    if (kind == GoType::KIND_CHAN)
+        return false;
+    if (kind == GoType::KIND_MAP)
+        return false;
     if (kind == GoType::KIND_STRING)
         return false;
     if (kind == GoType::KIND_UNSAFEPOINTER)
@@ -583,7 +592,8 @@ GoASTContext::IsPointerType(lldb::opaque
         case GoType::KIND_PTR:
         case GoType::KIND_UNSAFEPOINTER:
         case GoType::KIND_CHAN:
-            // TODO: is map a pointer? string? function?
+        case GoType::KIND_MAP:
+            // TODO: is function a pointer?
             return true;
         default:
             return false;
@@ -1064,6 +1074,11 @@ GoASTContext::GetNumChildren(lldb::opaqu
     {
         return array->GetLength();
     }
+    else if (t->IsTypedef())
+    {
+        return t->GetElementType().GetNumChildren(omit_empty_base_classes);
+    }
+
     return GetNumFields(type);
 }
 
@@ -1491,3 +1506,13 @@ GoASTContext::GetDWARFParser()
         m_dwarf_ast_parser_ap.reset(new DWARFASTParserGo(*this));
     return m_dwarf_ast_parser_ap.get();
 }
+
+UserExpression *
+GoASTContextForExpr::GetUserExpression(const char *expr, const char *expr_prefix, lldb::LanguageType language,
+                                       Expression::ResultType desired_type)
+{
+    TargetSP target = m_target_wp.lock();
+    if (target)
+        return new GoUserExpression(*target, expr, expr_prefix, language, desired_type);
+    return nullptr;
+}

Added: lldb/trunk/test/lang/go/expressions/TestExpressions.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/go/expressions/TestExpressions.py?rev=251820&view=auto
==============================================================================
--- lldb/trunk/test/lang/go/expressions/TestExpressions.py (added)
+++ lldb/trunk/test/lang/go/expressions/TestExpressions.py Mon Nov  2 13:30:40 2015
@@ -0,0 +1,113 @@
+"""Test the go expression parser/interpreter."""
+
+import os, time
+import unittest2
+import lldb
+import lldbutil
+from lldbtest import *
+
+class TestGoUserExpression(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    @python_api_test
+    @skipIfRemote # Not remote test suit ready
+    @skipUnlessGoInstalled
+    def test_with_dsym_and_python_api(self):
+        """Test GoASTUserExpress."""
+        self.buildGo()
+        self.launchProcess()
+        self.go_expressions()
+
+    def setUp(self):
+        # Call super's setUp().
+        TestBase.setUp(self)
+        # Find the line numbers to break inside main().
+        self.main_source = "main.go"
+        self.break_line = line_number(self.main_source, '// Set breakpoint here.')
+
+    def check_builtin(self, name, size=0, typeclass=lldb.eTypeClassBuiltin):
+        tl = self.target().FindTypes(name)
+        self.assertEqual(1, len(tl))
+        t = list(tl)[0]
+        self.assertEqual(name, t.name)
+        self.assertEqual(typeclass, t.type)
+        if size > 0:
+            self.assertEqual(size, t.size)
+
+    def launchProcess(self):
+        exe = os.path.join(os.getcwd(), "a.out")
+
+        target = self.dbg.CreateTarget(exe)
+        self.assertTrue(target, VALID_TARGET)
+
+        bpt = target.BreakpointCreateByLocation(self.main_source, self.break_line)
+        self.assertTrue(bpt, VALID_BREAKPOINT)
+
+        # Now launch the process, and do not stop at entry point.
+        process = target.LaunchSimple (None, None, self.get_process_working_directory())
+
+        self.assertTrue(process, PROCESS_IS_VALID)
+
+        # The stop reason of the thread should be breakpoint.
+        thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, bpt)
+
+        # Make sure we stopped at the first breakpoint.
+        self.assertTrue (len(thread_list) != 0, "No thread stopped at our breakpoint.")
+        self.assertTrue (len(thread_list) == 1, "More than one thread stopped at our breakpoint.")
+
+        frame = thread_list[0].GetFrameAtIndex(0)
+        self.assertTrue (frame, "Got a valid frame 0 frame.")
+
+    def go_expressions(self):
+        frame = self.frame()
+        v = frame.EvaluateExpression("1")
+        self.assertEqual(1, v.GetValueAsSigned())
+        x = frame.EvaluateExpression("x")
+        self.assertEqual(22, x.GetValueAsSigned())
+        
+        a = frame.EvaluateExpression("a")
+        self.assertEqual(3, a.GetNumChildren())
+        a0 = a.GetChildAtIndex(0)
+        self.assertEqual(8, a0.GetValueAsSigned())
+
+        # Array indexing
+        a0 = frame.EvaluateExpression("a[0]")
+        self.assertEqual(8, a0.GetValueAsSigned())
+        
+        # Slice indexing
+        b1 = frame.EvaluateExpression("b[1]")
+        self.assertEqual(9, b1.GetValueAsSigned())
+        
+        # Test global in this package
+        g = frame.EvaluateExpression("myGlobal")
+        self.assertEqual(17, g.GetValueAsSigned(), str(g))
+        
+        # Global with package name
+        g = frame.EvaluateExpression("main.myGlobal")
+        self.assertEqual(17, g.GetValueAsSigned(), str(g))
+        
+        # Global with quoted package name
+        g = frame.EvaluateExpression('"main".myGlobal')
+        self.assertEqual(17, g.GetValueAsSigned(), str(g))
+                
+        # Casting with package local type
+        s = frame.EvaluateExpression("*(*myStruct)(i.data)")
+        sb = s.GetChildMemberWithName("a")
+        self.assertEqual(2, sb.GetValueAsSigned())
+
+        # casting with explicit package
+        s = frame.EvaluateExpression("*(*main.myStruct)(i.data)")
+        sb = s.GetChildMemberWithName("a")
+        self.assertEqual(2, sb.GetValueAsSigned())
+
+        # Casting quoted package
+        s = frame.EvaluateExpression('*(*"main".myStruct)(i.data)')
+        sb = s.GetChildMemberWithName("b")
+        self.assertEqual(-1, sb.GetValueAsSigned())
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()

Added: lldb/trunk/test/lang/go/expressions/main.go
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/go/expressions/main.go?rev=251820&view=auto
==============================================================================
--- lldb/trunk/test/lang/go/expressions/main.go (added)
+++ lldb/trunk/test/lang/go/expressions/main.go Mon Nov  2 13:30:40 2015
@@ -0,0 +1,21 @@
+package main
+
+import "fmt"
+
+type myStruct struct {
+    a, b int
+}
+
+var myGlobal = 17
+
+func myFunc(i interface{}) {
+    a := [...]int{8, 9, 10}
+    b := a[:]
+    x := 22
+    fmt.Println(a, b, x, i, myGlobal)  // Set breakpoint here.
+}
+
+func main() {
+    s := myStruct {2, -1}
+    myFunc(s)
+}
\ No newline at end of file

Modified: lldb/trunk/unittests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/CMakeLists.txt?rev=251820&r1=251819&r2=251820&view=diff
==============================================================================
--- lldb/trunk/unittests/CMakeLists.txt (original)
+++ lldb/trunk/unittests/CMakeLists.txt Mon Nov  2 13:30:40 2015
@@ -24,6 +24,7 @@ function(add_lldb_unittest test_name)
 endfunction()
 
 add_subdirectory(Editline)
+add_subdirectory(Expression)
 add_subdirectory(Host)
 add_subdirectory(Interpreter)
 add_subdirectory(ScriptInterpreter)

Added: lldb/trunk/unittests/Expression/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Expression/CMakeLists.txt?rev=251820&view=auto
==============================================================================
--- lldb/trunk/unittests/Expression/CMakeLists.txt (added)
+++ lldb/trunk/unittests/Expression/CMakeLists.txt Mon Nov  2 13:30:40 2015
@@ -0,0 +1,3 @@
+add_lldb_unittest(ExpressionTests
+  GoParserTest.cpp
+  )

Added: lldb/trunk/unittests/Expression/GoParserTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Expression/GoParserTest.cpp?rev=251820&view=auto
==============================================================================
--- lldb/trunk/unittests/Expression/GoParserTest.cpp (added)
+++ lldb/trunk/unittests/Expression/GoParserTest.cpp Mon Nov  2 13:30:40 2015
@@ -0,0 +1,250 @@
+//===-- GoParserTest.cpp ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(_MSC_VER) && (_HAS_EXCEPTIONS == 0)
+// Workaround for MSVC standard library bug, which fails to include <thread> when
+// exceptions are disabled.
+#include <eh.h>
+#endif
+
+#include <sstream>
+
+#include "gtest/gtest.h"
+
+#include "lldb/Core/Error.h"
+#include "lldb/Expression/GoParser.h"
+
+using namespace lldb_private;
+
+namespace
+{
+struct ASTPrinter
+{
+    ASTPrinter(GoASTNode *n) { (*this)(n); }
+
+    void
+    operator()(GoASTNode *n)
+    {
+        if (n == nullptr)
+        {
+            m_stream << "nil ";
+            return;
+        }
+        m_stream << "(" << n->GetKindName() << " ";
+        n->WalkChildren(*this);
+        if (auto *nn = llvm::dyn_cast<GoASTAssignStmt>(n))
+            m_stream << nn->GetDefine() << " ";
+        if (auto *nn = llvm::dyn_cast<GoASTBasicLit>(n))
+            m_stream << nn->GetValue().m_value.str() << " ";
+        if (auto *nn = llvm::dyn_cast<GoASTBinaryExpr>(n))
+            m_stream << GoLexer::LookupToken(nn->GetOp()).str() << " ";
+        if (auto *nn = llvm::dyn_cast<GoASTIdent>(n))
+            m_stream << nn->GetName().m_value.str() << " ";
+        if (auto *nn = llvm::dyn_cast<GoASTBranchStmt>(n))
+            m_stream << GoLexer::LookupToken(nn->GetTok()).str() << " ";
+        if (auto *nn = llvm::dyn_cast<GoASTCallExpr>(n))
+            m_stream << (nn->GetEllipsis() ? "..." : "") << " ";
+        if (auto *nn = llvm::dyn_cast<GoASTChanType>(n))
+            m_stream << nn->GetDir() << " ";
+        if (auto *nn = llvm::dyn_cast<GoASTGenDecl>(n))
+            m_stream << GoLexer::LookupToken(nn->GetTok()).str() << " ";
+        if (auto *nn = llvm::dyn_cast<GoASTIncDecStmt>(n))
+            m_stream << GoLexer::LookupToken(nn->GetTok()).str() << " ";
+        if (auto *nn = llvm::dyn_cast<GoASTRangeStmt>(n))
+            m_stream << nn->GetDefine() << " ";
+        if (auto *nn = llvm::dyn_cast<GoASTSliceExpr>(n))
+            m_stream << nn->GetSlice3() << " ";
+        if (auto *nn = llvm::dyn_cast<GoASTUnaryExpr>(n))
+            m_stream << GoLexer::LookupToken(nn->GetOp()).str() << " ";
+        m_stream << ") ";
+    }
+
+    const std::string
+    str() const
+    {
+        return m_stream.str();
+    }
+    std::stringstream m_stream;
+};
+
+testing::AssertionResult
+CheckStatement(const char *_s, const char *c_expr, const char *sexpr, const char *code)
+{
+    GoParser parser(code);
+    std::unique_ptr<GoASTStmt> stmt(parser.Statement());
+    if (parser.Failed() || !stmt)
+    {
+        Error err;
+        parser.GetError(err);
+        return testing::AssertionFailure() << "Error parsing " << c_expr << "\n\t" << err.AsCString();
+    }
+    std::string actual_sexpr = ASTPrinter(stmt.get()).str();
+    if (actual_sexpr == sexpr)
+        return testing::AssertionSuccess();
+    return testing::AssertionFailure() << "Parsing: " << c_expr << "\nExpected: " << sexpr
+                                       << "\nGot:      " << actual_sexpr;
+}
+} // namespace
+
+#define EXPECT_PARSE(s, c) EXPECT_PRED_FORMAT2(CheckStatement, s, c)
+
+TEST(GoParserTest, ParseBasicLiterals)
+{
+    EXPECT_PARSE("(ExprStmt (BasicLit 0 ) ) ", "0");
+    EXPECT_PARSE("(ExprStmt (BasicLit 42 ) ) ", "42");
+    EXPECT_PARSE("(ExprStmt (BasicLit 0600 ) ) ", "0600");
+    EXPECT_PARSE("(ExprStmt (BasicLit 0xBadFace ) ) ", "0xBadFace");
+    EXPECT_PARSE("(ExprStmt (BasicLit 170141183460469231731687303715884105727 ) ) ",
+                 "170141183460469231731687303715884105727");
+
+    EXPECT_PARSE("(ExprStmt (BasicLit 0. ) ) ", "0.");
+    EXPECT_PARSE("(ExprStmt (BasicLit 72.40 ) ) ", "72.40");
+    EXPECT_PARSE("(ExprStmt (BasicLit 072.40 ) ) ", "072.40");
+    EXPECT_PARSE("(ExprStmt (BasicLit 2.71828 ) ) ", "2.71828");
+    EXPECT_PARSE("(ExprStmt (BasicLit 1.e+0 ) ) ", "1.e+0");
+    EXPECT_PARSE("(ExprStmt (BasicLit 6.67428e-11 ) ) ", "6.67428e-11");
+    EXPECT_PARSE("(ExprStmt (BasicLit 1E6 ) ) ", "1E6");
+    EXPECT_PARSE("(ExprStmt (BasicLit .12345E+6 ) ) ", ".12345E+6");
+
+    EXPECT_PARSE("(ExprStmt (BasicLit 0i ) ) ", "0i");
+    EXPECT_PARSE("(ExprStmt (BasicLit 011i ) ) ", "011i");
+    EXPECT_PARSE("(ExprStmt (BasicLit 0.i ) ) ", "0.i");
+    EXPECT_PARSE("(ExprStmt (BasicLit 2.71828i ) ) ", "2.71828i");
+    EXPECT_PARSE("(ExprStmt (BasicLit 6.67428e-11i ) ) ", "6.67428e-11i");
+    EXPECT_PARSE("(ExprStmt (BasicLit 1E6i ) ) ", "1E6i");
+    EXPECT_PARSE("(ExprStmt (BasicLit .12345E+6i ) ) ", ".12345E+6i");
+
+    EXPECT_PARSE("(ExprStmt (BasicLit 'a' ) ) ", "'a'");
+    EXPECT_PARSE("(ExprStmt (BasicLit '本' ) ) ", "'本'");
+    EXPECT_PARSE("(ExprStmt (BasicLit \"abc\" ) ) ", "\"abc\"");
+    EXPECT_PARSE("(ExprStmt (BasicLit `abc` ) ) ", "`abc`");
+    EXPECT_PARSE("(ExprStmt (BasicLit `ab\nc` ) ) ", "`ab\nc`");
+}
+
+TEST(GoParserTest, ParseOperand)
+{
+    EXPECT_PARSE("(ExprStmt (Ident a ) ) ", "a");
+    EXPECT_PARSE("(ExprStmt (Ident _x9 ) ) ", "_x9");
+    EXPECT_PARSE("(ExprStmt (Ident ThisVariableIsExported ) ) ", "ThisVariableIsExported");
+    EXPECT_PARSE("(ExprStmt (Ident αβ ) ) ", "αβ");
+
+    EXPECT_PARSE("(ExprStmt (SelectorExpr (Ident math ) (Ident Sin ) ) ) ", "math.Sin");
+}
+
+TEST(GoParserTest, ParseCompositeLiterals)
+{
+    EXPECT_PARSE("(ExprStmt (CompositeLit (Ident Point3D ) ) ) ", "Point3D{}");
+    EXPECT_PARSE("(ExprStmt (CompositeLit (Ident Line ) (Ident origin ) (CompositeLit (Ident Point3D ) (KeyValueExpr "
+                 "(Ident y ) (UnaryExpr (BasicLit 4 ) - ) ) (KeyValueExpr (Ident z ) (BasicLit 12.3 ) ) ) ) ) ",
+                 "Line{origin, Point3D{y: -4, z: 12.3}}");
+    EXPECT_PARSE("(ExprStmt (CompositeLit (ArrayType (BasicLit 10 ) (Ident string ) ) ) ) ", "[10]string{}");
+    EXPECT_PARSE("(ExprStmt (CompositeLit (ArrayType (BasicLit 6 ) (Ident int ) ) (BasicLit 1 ) (BasicLit 2 ) "
+                 "(BasicLit 3 ) (BasicLit 5 ) ) ) ",
+                 "[6]int {1, 2, 3, 5}");
+    EXPECT_PARSE("(ExprStmt (CompositeLit (ArrayType nil (Ident int ) ) (BasicLit 2 ) (BasicLit 3 ) (BasicLit 5 ) "
+                 "(BasicLit 7 ) (BasicLit 9 ) (BasicLit 2147483647 ) ) ) ",
+                 "[]int{2, 3, 5, 7, 9, 2147483647}");
+    EXPECT_PARSE("(ExprStmt (CompositeLit (ArrayType (BasicLit 128 ) (Ident bool ) ) (KeyValueExpr (BasicLit 'a' ) "
+                 "(Ident true ) ) (KeyValueExpr (BasicLit 'e' ) (Ident true ) ) (KeyValueExpr (BasicLit 'i' ) (Ident "
+                 "true ) ) (KeyValueExpr (BasicLit 'o' ) (Ident true ) ) (KeyValueExpr (BasicLit 'u' ) (Ident true ) ) "
+                 "(KeyValueExpr (BasicLit 'y' ) (Ident true ) ) ) ) ",
+                 "[128]bool{'a': true, 'e': true, 'i': true, 'o': true, 'u': true, 'y': true}");
+    EXPECT_PARSE("(ExprStmt (CompositeLit (ArrayType (BasicLit 10 ) (Ident float32 ) ) (UnaryExpr (BasicLit 1 ) - ) "
+                 "(KeyValueExpr (BasicLit 4 ) (UnaryExpr (BasicLit 0.1 ) - ) ) (UnaryExpr (BasicLit 0.1 ) - ) "
+                 "(KeyValueExpr (BasicLit 9 ) (UnaryExpr (BasicLit 1 ) - ) ) ) ) ",
+                 "[10]float32{-1, 4: -0.1, -0.1, 9: -1}");
+}
+
+TEST(GoParserTest, ParseEllipsisArray)
+{
+    EXPECT_PARSE(
+        "(ExprStmt (CompositeLit (ArrayType (Ellipsis nil ) (Ident string ) ) (BasicLit `Sat` ) (BasicLit `Sun` ) ) ) ",
+        "[...]string {`Sat`, `Sun`}");
+    EXPECT_PARSE("(ExprStmt (CompositeLit (ArrayType (Ellipsis nil ) (Ident Point ) ) (CompositeLit nil (BasicLit 1.5 "
+                 ") (UnaryExpr (BasicLit 3.5 ) - ) ) (CompositeLit nil (BasicLit 0 ) (BasicLit 0 ) ) ) ) ",
+                 "[...]Point{{1.5, -3.5}, {0, 0}}");
+}
+
+TEST(GoParserTest, ParseMap)
+{
+    EXPECT_PARSE("(ExprStmt (CompositeLit (MapType (Ident string ) (Ident float32 ) ) (KeyValueExpr (BasicLit `C0` ) "
+                 "(BasicLit 16.35 ) ) (KeyValueExpr (BasicLit `D0` ) (BasicLit 18.35 ) ) ) ) ",
+                 "map[string]float32{`C0`: 16.35, `D0`: 18.35, }");
+}
+
+TEST(GoParserTest, UnaryExpr)
+{
+    EXPECT_PARSE("(ExprStmt (UnaryExpr (Ident x ) + ) ) ", "+x");
+    EXPECT_PARSE("(ExprStmt (UnaryExpr (Ident x ) - ) ) ", "-x");
+    EXPECT_PARSE("(ExprStmt (UnaryExpr (Ident x ) ! ) ) ", "!x");
+    EXPECT_PARSE("(ExprStmt (UnaryExpr (Ident x ) ^ ) ) ", "^x");
+    EXPECT_PARSE("(ExprStmt (UnaryExpr (Ident x ) & ) ) ", "&x");
+    EXPECT_PARSE("(ExprStmt (UnaryExpr (Ident x ) <- ) ) ", "<-x");
+    EXPECT_PARSE("(ExprStmt (StarExpr (Ident x ) ) ) ", "*x");
+}
+
+TEST(GoParserTest, BinaryExpr)
+{
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) || ) ) ", "a || b");
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) && ) ) ", "a && b");
+
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) == ) ) ", "a == b");
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) != ) ) ", "a != b");
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) < ) ) ", "a < b");
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) <= ) ) ", "a <= b");
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) > ) ) ", "a > b");
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) >= ) ) ", "a >= b");
+
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) + ) ) ", "a + b");
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) - ) ) ", "a - b");
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) | ) ) ", "a | b");
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) ^ ) ) ", "a ^ b");
+
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) * ) ) ", "a * b");
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) / ) ) ", "a / b");
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) % ) ) ", "a % b");
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) << ) ) ", "a << b");
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) >> ) ) ", "a >> b");
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) & ) ) ", "a & b");
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) &^ ) ) ", "a &^ b");
+
+    EXPECT_PARSE(
+        "(ExprStmt (BinaryExpr (BasicLit 23 ) (BinaryExpr (BasicLit 3 ) (IndexExpr (Ident x ) (Ident i ) ) * ) + ) ) ",
+        "23 + 3*x[i]");
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (UnaryExpr (UnaryExpr (Ident a ) + ) + ) + ) ) ", "a + + + a");
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (UnaryExpr (Ident a ) ^ ) (Ident b ) >> ) ) ", "^a >> b");
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (CallExpr (Ident f )  ) (CallExpr (Ident g )  ) || ) ) ", "f() || g()");
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (BinaryExpr (Ident x ) (BinaryExpr (Ident y ) (BasicLit 1 ) + ) == ) "
+                 "(BinaryExpr (UnaryExpr (Ident chanPtr ) <- ) (BasicLit 0 ) > ) && ) ) ",
+                 "x == y+1 && <-chanPtr > 0");
+}
+
+TEST(GoParserTest, PrimaryExpr)
+{
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident x ) (CallExpr (Ident f )  ) <= ) ) ", "x <= f()");
+    EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident s ) (BasicLit `.txt` ) + ) ) ", "(s + `.txt`)");
+    EXPECT_PARSE("(ExprStmt (CallExpr (Ident f ) (BasicLit 3.1415 ) (Ident true )  ) ) ", "f(3.1415, true)");
+    EXPECT_PARSE("(ExprStmt (CallExpr (Ident f ) (BasicLit 3.1415 ) (Ident a ) ... ) ) ", "f(3.1415, a...)");
+    EXPECT_PARSE("(ExprStmt (IndexExpr (Ident m ) (BasicLit '1' ) ) ) ", "m['1']");
+    EXPECT_PARSE("(ExprStmt (SliceExpr (Ident s ) (Ident i ) (BinaryExpr (Ident j ) (BasicLit 1 ) + ) nil 0 ) ) ",
+                 "s[i : j + 1]");
+    EXPECT_PARSE("(ExprStmt (SelectorExpr (Ident obj ) (Ident color ) ) ) ", "obj.color");
+    EXPECT_PARSE("(ExprStmt (CallExpr (SelectorExpr (IndexExpr (SelectorExpr (Ident f ) (Ident p ) ) (Ident i ) ) "
+                 "(Ident x ) )  ) ) ",
+                 "f.p[i].x()");
+}
+
+TEST(GoParserTest, Conversions)
+{
+    EXPECT_PARSE("(ExprStmt (StarExpr (CallExpr (Ident Point ) (Ident p )  ) ) ) ", "*Point(p)");
+    EXPECT_PARSE("(ExprStmt (CallExpr (StarExpr (Ident Point ) ) (Ident p )  ) ) ", "(*Point)(p)");
+    EXPECT_PARSE("(ExprStmt (UnaryExpr (CallExpr (ChanType (Ident int ) 0 ) (Ident c )  ) <- ) ) ", "<-chan int(c)");
+    EXPECT_PARSE("(ExprStmt (TypeAssertExpr (Ident y ) (SelectorExpr (Ident io ) (Ident Reader ) ) ) ) ",
+                 "y.(io.Reader)");
+}




More information about the lldb-commits mailing list