1 //===-- ClangREPL.cpp -----------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "ClangREPL.h"
10 #include "lldb/Core/Debugger.h"
11 #include "lldb/Core/PluginManager.h"
12 #include "lldb/Expression/ExpressionVariable.h"
13 
14 using namespace lldb_private;
15 
16 LLDB_PLUGIN_DEFINE(ClangREPL)
17 
18 char ClangREPL::ID;
19 
ClangREPL(lldb::LanguageType language,Target & target)20 ClangREPL::ClangREPL(lldb::LanguageType language, Target &target)
21     : llvm::RTTIExtends<ClangREPL, REPL>(target), m_language(language),
22       m_implicit_expr_result_regex("\\$[0-9]+") {}
23 
24 ClangREPL::~ClangREPL() = default;
25 
Initialize()26 void ClangREPL::Initialize() {
27   LanguageSet languages;
28   // FIXME: There isn't a way to ask CPlusPlusLanguage and ObjCLanguage for
29   // a list of languages they support.
30   languages.Insert(lldb::LanguageType::eLanguageTypeC);
31   languages.Insert(lldb::LanguageType::eLanguageTypeC89);
32   languages.Insert(lldb::LanguageType::eLanguageTypeC99);
33   languages.Insert(lldb::LanguageType::eLanguageTypeC11);
34   languages.Insert(lldb::LanguageType::eLanguageTypeC_plus_plus);
35   languages.Insert(lldb::LanguageType::eLanguageTypeC_plus_plus_03);
36   languages.Insert(lldb::LanguageType::eLanguageTypeC_plus_plus_11);
37   languages.Insert(lldb::LanguageType::eLanguageTypeC_plus_plus_14);
38   languages.Insert(lldb::LanguageType::eLanguageTypeObjC);
39   languages.Insert(lldb::LanguageType::eLanguageTypeObjC_plus_plus);
40   PluginManager::RegisterPlugin(GetPluginNameStatic(), "C language REPL",
41                                 &CreateInstance, languages);
42 }
43 
Terminate()44 void ClangREPL::Terminate() {
45   PluginManager::UnregisterPlugin(&CreateInstance);
46 }
47 
CreateInstance(Status & error,lldb::LanguageType language,Debugger * debugger,Target * target,const char * repl_options)48 lldb::REPLSP ClangREPL::CreateInstance(Status &error,
49                                        lldb::LanguageType language,
50                                        Debugger *debugger, Target *target,
51                                        const char *repl_options) {
52   // Creating a dummy target if only a debugger is given isn't implemented yet.
53   if (!target) {
54     error.SetErrorString("must have a target to create a REPL");
55     return nullptr;
56   }
57   lldb::REPLSP result = std::make_shared<ClangREPL>(language, *target);
58   target->SetREPL(language, result);
59   error = Status();
60   return result;
61 }
62 
DoInitialization()63 Status ClangREPL::DoInitialization() { return Status(); }
64 
GetSourceFileBasename()65 llvm::StringRef ClangREPL::GetSourceFileBasename() {
66   static constexpr llvm::StringLiteral g_repl("repl.c");
67   return g_repl;
68 }
69 
GetAutoIndentCharacters()70 const char *ClangREPL::GetAutoIndentCharacters() { return "  "; }
71 
SourceIsComplete(const std::string & source)72 bool ClangREPL::SourceIsComplete(const std::string &source) {
73   // FIXME: There isn't a good way to know if the input source is complete or
74   // not, so just say that every single REPL line is ready to be parsed.
75   return !source.empty();
76 }
77 
GetDesiredIndentation(const StringList & lines,int cursor_position,int tab_size)78 lldb::offset_t ClangREPL::GetDesiredIndentation(const StringList &lines,
79                                                 int cursor_position,
80                                                 int tab_size) {
81   // FIXME: Not implemented.
82   return LLDB_INVALID_OFFSET;
83 }
84 
GetLanguage()85 lldb::LanguageType ClangREPL::GetLanguage() { return m_language; }
86 
PrintOneVariable(Debugger & debugger,lldb::StreamFileSP & output_sp,lldb::ValueObjectSP & valobj_sp,ExpressionVariable * var)87 bool ClangREPL::PrintOneVariable(Debugger &debugger,
88                                  lldb::StreamFileSP &output_sp,
89                                  lldb::ValueObjectSP &valobj_sp,
90                                  ExpressionVariable *var) {
91   // If a ExpressionVariable was passed, check first if that variable is just
92   // an automatically created expression result. These variables are already
93   // printed by the REPL so this is done to prevent printing the variable twice.
94   if (var) {
95     if (m_implicit_expr_result_regex.Execute(var->GetName().GetStringRef()))
96       return true;
97   }
98   valobj_sp->Dump(*output_sp);
99   return true;
100 }
101 
CompleteCode(const std::string & current_code,CompletionRequest & request)102 void ClangREPL::CompleteCode(const std::string &current_code,
103                              CompletionRequest &request) {
104   // Not implemented.
105 }
106