xref: /llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp (revision 2861324208e13846eb306f01b32448f94177cc3b)
1 //===-- ScriptInterpreterLua.cpp --------------------------------*- 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 #include "ScriptInterpreterLua.h"
10 #include "Lua.h"
11 #include "lldb/Core/Debugger.h"
12 #include "lldb/Core/PluginManager.h"
13 #include "lldb/Core/StreamFile.h"
14 #include "lldb/Interpreter/CommandReturnObject.h"
15 #include "lldb/Utility/Stream.h"
16 #include "lldb/Utility/StringList.h"
17 #include "lldb/Utility/Timer.h"
18 
19 using namespace lldb;
20 using namespace lldb_private;
21 
22 class IOHandlerLuaInterpreter : public IOHandlerDelegate,
23                                 public IOHandlerEditline {
24 public:
25   IOHandlerLuaInterpreter(Debugger &debugger)
26       : IOHandlerEditline(debugger, IOHandler::Type::LuaInterpreter, "lua",
27                           ">>> ", "..> ", true, debugger.GetUseColor(), 0,
28                           *this, nullptr),
29         m_lua() {}
30 
31   void IOHandlerInputComplete(IOHandler &io_handler,
32                               std::string &data) override {
33     if (llvm::Error error = m_lua.Run(data)) {
34       *GetOutputStreamFileSP() << llvm::toString(std::move(error));
35     }
36   }
37 
38 private:
39   Lua m_lua;
40 };
41 
42 ScriptInterpreterLua::ScriptInterpreterLua(Debugger &debugger)
43     : ScriptInterpreter(debugger, eScriptLanguageLua) {}
44 
45 ScriptInterpreterLua::~ScriptInterpreterLua() {}
46 
47 bool ScriptInterpreterLua::ExecuteOneLine(llvm::StringRef command,
48                                           CommandReturnObject *result,
49                                           const ExecuteScriptOptions &options) {
50   Lua l;
51   if (llvm::Error e = l.Run(command)) {
52     result->AppendErrorWithFormatv(
53         "lua failed attempting to evaluate '{0}': {1}\n", command,
54         llvm::toString(std::move(e)));
55     return false;
56   }
57   return true;
58 }
59 
60 void ScriptInterpreterLua::ExecuteInterpreterLoop() {
61   static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
62   Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
63 
64   Debugger &debugger = m_debugger;
65 
66   // At the moment, the only time the debugger does not have an input file
67   // handle is when this is called directly from lua, in which case it is
68   // both dangerous and unnecessary (not to mention confusing) to try to embed
69   // a running interpreter loop inside the already running lua interpreter
70   // loop, so we won't do it.
71 
72   if (!debugger.GetInputFile().IsValid())
73     return;
74 
75   IOHandlerSP io_handler_sp(new IOHandlerLuaInterpreter(debugger));
76   debugger.PushIOHandler(io_handler_sp);
77 }
78 
79 void ScriptInterpreterLua::Initialize() {
80   static llvm::once_flag g_once_flag;
81 
82   llvm::call_once(g_once_flag, []() {
83     PluginManager::RegisterPlugin(GetPluginNameStatic(),
84                                   GetPluginDescriptionStatic(),
85                                   lldb::eScriptLanguageLua, CreateInstance);
86   });
87 }
88 
89 void ScriptInterpreterLua::Terminate() {}
90 
91 lldb::ScriptInterpreterSP
92 ScriptInterpreterLua::CreateInstance(Debugger &debugger) {
93   return std::make_shared<ScriptInterpreterLua>(debugger);
94 }
95 
96 lldb_private::ConstString ScriptInterpreterLua::GetPluginNameStatic() {
97   static ConstString g_name("script-lua");
98   return g_name;
99 }
100 
101 const char *ScriptInterpreterLua::GetPluginDescriptionStatic() {
102   return "Lua script interpreter";
103 }
104 
105 lldb_private::ConstString ScriptInterpreterLua::GetPluginName() {
106   return GetPluginNameStatic();
107 }
108 
109 uint32_t ScriptInterpreterLua::GetPluginVersion() { return 1; }
110