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
19namespace lldb_private {
20
21class REPL : public IOHandlerDelegate {
22public:
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
109protected:
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
155private:
156  std::string GetSourcePath();
157};
158
159} // namespace lldb_private
160
161#endif // lldb_REPL_h
162