1 //===-- REPL.h --------------------------------------------------*- C++ -*-===//
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 #ifndef lldb_REPL_h
10 #define lldb_REPL_h
11 
12 #include <string>
13 
14 #include "lldb/Core/IOHandler.h"
15 #include "lldb/Interpreter/OptionGroupFormat.h"
16 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
17 #include "lldb/Target/Target.h"
18 
19 namespace lldb_private {
20 
21 class REPL : public IOHandlerDelegate {
22 public:
23   // See TypeSystem.h for how to add subclasses to this.
24   enum LLVMCastKind { eKindClang, eKindSwift, eKindGo, kNumKinds };
25 
26   LLVMCastKind getKind() const { return m_kind; }
27 
28   REPL(LLVMCastKind kind, Target &target);
29 
30   ~REPL() override;
31 
32   /// Get a REPL with an existing target (or, failing that, a debugger to use),
33   /// and (optional) extra arguments for the compiler.
34   ///
35   /// \param[out] Status
36   ///     If this language is supported but the REPL couldn't be created, this
37   ///     error is populated with the reason.
38   ///
39   /// \param[in] language
40   ///     The language to create a REPL for.
41   ///
42   /// \param[in] debugger
43   ///     If provided, and target is nullptr, the debugger to use when setting
44   ///     up a top-level REPL.
45   ///
46   /// \param[in] target
47   ///     If provided, the target to put the REPL inside.
48   ///
49   /// \param[in] repl_options
50   ///     If provided, additional options for the compiler when parsing REPL
51   ///     expressions.
52   ///
53   /// \return
54   ///     The range of the containing object in the target process.
55   static lldb::REPLSP Create(Status &Status, lldb::LanguageType language,
56                              Debugger *debugger, Target *target,
57                              const char *repl_options);
58 
59   void SetFormatOptions(const OptionGroupFormat &options) {
60     m_format_options = options;
61   }
62 
63   void
64   SetValueObjectDisplayOptions(const OptionGroupValueObjectDisplay &options) {
65     m_varobj_options = options;
66   }
67 
68   void SetEvaluateOptions(const EvaluateExpressionOptions &options) {
69     m_expr_options = options;
70   }
71 
72   void SetCompilerOptions(const char *options) {
73     if (options)
74       m_compiler_options = options;
75   }
76 
77   lldb::IOHandlerSP GetIOHandler();
78 
79   Status RunLoop();
80 
81   // IOHandler::Delegate functions
82   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override;
83 
84   bool IOHandlerInterrupt(IOHandler &io_handler) override;
85 
86   void IOHandlerInputInterrupted(IOHandler &io_handler,
87                                  std::string &line) override;
88 
89   const char *IOHandlerGetFixIndentationCharacters() override;
90 
91   ConstString IOHandlerGetControlSequence(char ch) override;
92 
93   const char *IOHandlerGetCommandPrefix() override;
94 
95   const char *IOHandlerGetHelpPrologue() override;
96 
97   bool IOHandlerIsInputComplete(IOHandler &io_handler,
98                                 StringList &lines) override;
99 
100   int IOHandlerFixIndentation(IOHandler &io_handler, const StringList &lines,
101                               int cursor_position) override;
102 
103   void IOHandlerInputComplete(IOHandler &io_handler,
104                               std::string &line) override;
105 
106   void IOHandlerComplete(IOHandler &io_handler,
107                          CompletionRequest &request) override;
108 
109 protected:
110   static int CalculateActualIndentation(const StringList &lines);
111 
112   // Subclasses should override these functions to implement a functional REPL.
113 
114   virtual Status DoInitialization() = 0;
115 
116   virtual ConstString GetSourceFileBasename() = 0;
117 
118   virtual const char *GetAutoIndentCharacters() = 0;
119 
120   virtual bool SourceIsComplete(const std::string &source) = 0;
121 
122   virtual lldb::offset_t GetDesiredIndentation(
123       const StringList &lines, int cursor_position,
124       int tab_size) = 0; // LLDB_INVALID_OFFSET means no change
125 
126   virtual lldb::LanguageType GetLanguage() = 0;
127 
128   virtual bool PrintOneVariable(Debugger &debugger,
129                                 lldb::StreamFileSP &output_sp,
130                                 lldb::ValueObjectSP &valobj_sp,
131                                 ExpressionVariable *var = nullptr) = 0;
132 
133   virtual int CompleteCode(const std::string &current_code,
134                            StringList &matches) = 0;
135 
136   OptionGroupFormat m_format_options = OptionGroupFormat(lldb::eFormatDefault);
137   OptionGroupValueObjectDisplay m_varobj_options;
138   EvaluateExpressionOptions m_expr_options;
139   std::string m_compiler_options;
140 
141   bool m_enable_auto_indent = true;
142   std::string m_indent_str; // Use this string for each level of indentation
143   std::string m_current_indent_str;
144   uint32_t m_current_indent_level = 0;
145 
146   std::string m_repl_source_path;
147   bool m_dedicated_repl_mode = false;
148 
149   StringList m_code; // All accumulated REPL statements are saved here
150 
151   Target &m_target;
152   lldb::IOHandlerSP m_io_handler_sp;
153   LLVMCastKind m_kind;
154 
155 private:
156   std::string GetSourcePath();
157 };
158 
159 } // namespace lldb_private
160 
161 #endif // lldb_REPL_h
162