This revision was automatically updated to reflect the committed changes.
Closed by commit rGc22329972f02: [lldb] Add a C language REPL to test 
LLDB's REPL infrastructure (authored by teemperor).
Herald added a subscriber: lldb-commits.

Changed prior to commit:
  https://reviews.llvm.org/D87281?vs=323168&id=374615#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D87281/new/

https://reviews.llvm.org/D87281

Files:
  lldb/source/Commands/Options.td
  lldb/source/Plugins/CMakeLists.txt
  lldb/source/Plugins/REPL/CMakeLists.txt
  lldb/source/Plugins/REPL/Clang/CMakeLists.txt
  lldb/source/Plugins/REPL/Clang/ClangREPL.cpp
  lldb/source/Plugins/REPL/Clang/ClangREPL.h
  lldb/test/API/repl/clang/Makefile
  lldb/test/API/repl/clang/TestClangREPL.py
  lldb/test/API/repl/clang/main.c

Index: lldb/test/API/repl/clang/main.c
===================================================================
--- /dev/null
+++ lldb/test/API/repl/clang/main.c
@@ -0,0 +1,3 @@
+int main(int argc, char **argv) {
+  return 0;
+}
Index: lldb/test/API/repl/clang/TestClangREPL.py
===================================================================
--- /dev/null
+++ lldb/test/API/repl/clang/TestClangREPL.py
@@ -0,0 +1,54 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.lldbpexpect import PExpectTest
+
+class TestCase(PExpectTest):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    def expect_repl(self, expr, substrs=[]):
+        """ Evaluates the expression in the REPL and verifies that the list
+        of substrs is in the REPL output."""
+        # Only single line expressions supported.
+        self.assertNotIn("\n", expr)
+        self.child.send(expr + "\n")
+        for substr in substrs:
+            self.child.expect_exact(substr)
+        # Look for the start of the next REPL input line.
+        self.current_repl_line_number += 1
+        self.child.expect_exact(str(self.current_repl_line_number) + ">")
+
+    # PExpect uses many timeouts internally and doesn't play well
+    # under ASAN on a loaded machine..
+    @skipIfAsan
+    @skipIfEditlineSupportMissing
+    def test_basic_completion(self):
+        """Test that we can complete a simple multiline expression"""
+        self.build()
+        self.current_repl_line_number = 1
+
+        self.launch(executable=self.getBuildArtifact("a.out"), dimensions=(100,500))
+        # Try launching the REPL before we have a running target.
+        self.expect("expression --repl -l c --", substrs=["REPL requires a running target process."])
+
+        self.expect("b main", substrs=["Breakpoint 1", "address ="])
+        self.expect("run", substrs=["stop reason = breakpoint 1"])
+
+        # Start the REPL.
+        self.child.send("expression --repl -l c --\n")
+        self.child.expect_exact("1>")
+
+        # Try evaluating a simple expression.
+        self.expect_repl("3 + 3", substrs=["(int) $0 = 6"])
+
+        # Try declaring a persistent variable.
+        self.expect_repl("long $persistent = 7; 5",
+                         substrs=["(int) $1 = 5",
+                                  "(long) $persistent = 7"])
+
+        # Try using the persistent variable from before.
+        self.expect_repl("$persistent + 10",
+                         substrs=["(long) $2 = 17"])
+
+        self.quit()
Index: lldb/test/API/repl/clang/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/repl/clang/Makefile
@@ -0,0 +1,2 @@
+C_SOURCES := main.c
+include Makefile.rules
Index: lldb/source/Plugins/REPL/Clang/ClangREPL.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/REPL/Clang/ClangREPL.h
@@ -0,0 +1,65 @@
+//===-- ClangREPL.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_REPL_CLANG_CLANGREPL_H
+#define LLDB_SOURCE_PLUGINS_REPL_CLANG_CLANGREPL_H
+
+#include "lldb/Expression/REPL.h"
+
+namespace lldb_private {
+/// Implements a Clang-based REPL for C languages on top of LLDB's REPL
+/// framework.
+class ClangREPL : public REPL {
+public:
+  ClangREPL(lldb::LanguageType language, Target &target);
+
+  ~ClangREPL() override;
+
+  static void Initialize();
+
+  static void Terminate();
+
+  static lldb::REPLSP CreateInstance(Status &error, lldb::LanguageType language,
+                                     Debugger *debugger, Target *target,
+                                     const char *repl_options);
+
+  static lldb_private::ConstString GetPluginNameStatic() {
+    return ConstString("ClangREPL");
+  }
+
+protected:
+  Status DoInitialization() override;
+
+  ConstString GetSourceFileBasename() override;
+
+  const char *GetAutoIndentCharacters() override;
+
+  bool SourceIsComplete(const std::string &source) override;
+
+  lldb::offset_t GetDesiredIndentation(const StringList &lines,
+                                       int cursor_position,
+                                       int tab_size) override;
+
+  lldb::LanguageType GetLanguage() override;
+
+  bool PrintOneVariable(Debugger &debugger, lldb::StreamFileSP &output_sp,
+                        lldb::ValueObjectSP &valobj_sp,
+                        ExpressionVariable *var = nullptr) override;
+
+  void CompleteCode(const std::string &current_code,
+                    CompletionRequest &request) override;
+
+private:
+  /// The specific C language of this REPL.
+  lldb::LanguageType m_language;
+  /// A regex matching the implicitly created LLDB result variables.
+  lldb_private::RegularExpression m_implicit_expr_result_regex;
+};
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_REPL_CLANG_CLANGREPL_H
Index: lldb/source/Plugins/REPL/Clang/ClangREPL.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/REPL/Clang/ClangREPL.cpp
@@ -0,0 +1,102 @@
+//===-- ClangREPL.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangREPL.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Expression/ExpressionVariable.h"
+
+using namespace lldb_private;
+
+LLDB_PLUGIN_DEFINE(ClangREPL)
+
+ClangREPL::ClangREPL(lldb::LanguageType language, Target &target)
+    : REPL(eKindClang, target), m_language(language),
+      m_implicit_expr_result_regex("\\$[0-9]+") {}
+
+ClangREPL::~ClangREPL() {}
+
+void ClangREPL::Initialize() {
+  LanguageSet languages;
+  // FIXME: There isn't a way to ask CPlusPlusLanguage and ObjCLanguage for
+  // a list of languages they support.
+  languages.Insert(lldb::LanguageType::eLanguageTypeC);
+  languages.Insert(lldb::LanguageType::eLanguageTypeC89);
+  languages.Insert(lldb::LanguageType::eLanguageTypeC99);
+  languages.Insert(lldb::LanguageType::eLanguageTypeC11);
+  languages.Insert(lldb::LanguageType::eLanguageTypeC_plus_plus);
+  languages.Insert(lldb::LanguageType::eLanguageTypeC_plus_plus_03);
+  languages.Insert(lldb::LanguageType::eLanguageTypeC_plus_plus_11);
+  languages.Insert(lldb::LanguageType::eLanguageTypeC_plus_plus_14);
+  languages.Insert(lldb::LanguageType::eLanguageTypeObjC);
+  languages.Insert(lldb::LanguageType::eLanguageTypeObjC_plus_plus);
+  PluginManager::RegisterPlugin(GetPluginNameStatic(), "C language REPL",
+                                &CreateInstance, languages);
+}
+
+void ClangREPL::Terminate() {
+  PluginManager::UnregisterPlugin(&CreateInstance);
+}
+
+lldb::REPLSP ClangREPL::CreateInstance(Status &error,
+                                       lldb::LanguageType language,
+                                       Debugger *debugger, Target *target,
+                                       const char *repl_options) {
+  // Creating a dummy target if only a debugger is given isn't implemented yet.
+  if (!target) {
+    error.SetErrorString("must have a target to create a REPL");
+    return nullptr;
+  }
+  lldb::REPLSP result = std::make_shared<ClangREPL>(language, *target);
+  target->SetREPL(language, result);
+  error = Status();
+  return result;
+}
+
+Status ClangREPL::DoInitialization() { return Status(); }
+
+ConstString ClangREPL::GetSourceFileBasename() {
+  return ConstString("repl.c");
+}
+
+const char *ClangREPL::GetAutoIndentCharacters() { return "  "; }
+
+bool ClangREPL::SourceIsComplete(const std::string &source) {
+  // FIXME: There isn't a good way to know if the input source is complete or
+  // not, so just say that every single REPL line is ready to be parsed.
+  return !source.empty();
+}
+
+lldb::offset_t ClangREPL::GetDesiredIndentation(const StringList &lines,
+                                                int cursor_position,
+                                                int tab_size) {
+  // FIXME: Not implemented.
+  return LLDB_INVALID_OFFSET;
+}
+
+lldb::LanguageType ClangREPL::GetLanguage() { return m_language; }
+
+bool ClangREPL::PrintOneVariable(Debugger &debugger,
+                                 lldb::StreamFileSP &output_sp,
+                                 lldb::ValueObjectSP &valobj_sp,
+                                 ExpressionVariable *var) {
+  // If a ExpressionVariable was passed, check first if that variable is just
+  // an automatically created expression result. These variables are already
+  // printed by the REPL so this is done to prevent printing the variable twice.
+  if (var) {
+    if (m_implicit_expr_result_regex.Execute(var->GetName().GetStringRef()))
+      return true;
+  }
+  valobj_sp->Dump(*output_sp);
+  return true;
+}
+
+void ClangREPL::CompleteCode(const std::string &current_code,
+                             CompletionRequest &request) {
+  // Not implemented.
+}
Index: lldb/source/Plugins/REPL/Clang/CMakeLists.txt
===================================================================
--- /dev/null
+++ lldb/source/Plugins/REPL/Clang/CMakeLists.txt
@@ -0,0 +1,17 @@
+add_lldb_library(lldbPluginClangREPL PLUGIN
+  ClangREPL.cpp
+
+  LINK_LIBS
+    lldbCore
+    lldbDataFormatters
+    lldbHost
+    lldbSymbol
+    lldbTarget
+    lldbUtility
+    lldbPluginClangCommon
+    lldbPluginCPPRuntime
+    lldbPluginTypeSystemClang
+
+  LINK_COMPONENTS
+    Support
+)
Index: lldb/source/Plugins/REPL/CMakeLists.txt
===================================================================
--- /dev/null
+++ lldb/source/Plugins/REPL/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(Clang)
Index: lldb/source/Plugins/CMakeLists.txt
===================================================================
--- lldb/source/Plugins/CMakeLists.txt
+++ lldb/source/Plugins/CMakeLists.txt
@@ -14,6 +14,7 @@
 add_subdirectory(OperatingSystem)
 add_subdirectory(Platform)
 add_subdirectory(Process)
+add_subdirectory(REPL)
 add_subdirectory(ScriptInterpreter)
 add_subdirectory(StructuredData)
 add_subdirectory(SymbolFile)
Index: lldb/source/Commands/Options.td
===================================================================
--- lldb/source/Commands/Options.td
+++ lldb/source/Commands/Options.td
@@ -355,7 +355,7 @@
     Desc<"When specified, debug the JIT code by setting a breakpoint on the "
     "first instruction and forcing breakpoints to not be ignored (-i0) and no "
     "unwinding to happen on error (-u0).">;
-  def expression_options_language : Option<"language", "l">, Groups<[1,2]>,
+  def expression_options_language : Option<"language", "l">, Groups<[1,2,3]>,
     Arg<"Language">, Desc<"Specifies the Language to use when parsing the "
     "expression.  If not set the target.language setting is used.">;
   def expression_options_apply_fixits : Option<"apply-fixits", "X">,
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to