167de8962SJonas Devlieghere //===-- ScriptInterpreterLua.cpp --------------------------------*- C++ -*-===//
267de8962SJonas Devlieghere //
367de8962SJonas Devlieghere // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
467de8962SJonas Devlieghere // See https://llvm.org/LICENSE.txt for license information.
567de8962SJonas Devlieghere // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
667de8962SJonas Devlieghere //
767de8962SJonas Devlieghere //===----------------------------------------------------------------------===//
867de8962SJonas Devlieghere 
967de8962SJonas Devlieghere #include "ScriptInterpreterLua.h"
10*28613242SJonas Devlieghere #include "Lua.h"
1167de8962SJonas Devlieghere #include "lldb/Core/Debugger.h"
1267de8962SJonas Devlieghere #include "lldb/Core/PluginManager.h"
1367de8962SJonas Devlieghere #include "lldb/Core/StreamFile.h"
14*28613242SJonas Devlieghere #include "lldb/Interpreter/CommandReturnObject.h"
1567de8962SJonas Devlieghere #include "lldb/Utility/Stream.h"
1667de8962SJonas Devlieghere #include "lldb/Utility/StringList.h"
17*28613242SJonas Devlieghere #include "lldb/Utility/Timer.h"
1867de8962SJonas Devlieghere 
1967de8962SJonas Devlieghere using namespace lldb;
2067de8962SJonas Devlieghere using namespace lldb_private;
2167de8962SJonas Devlieghere 
22*28613242SJonas Devlieghere class IOHandlerLuaInterpreter : public IOHandlerDelegate,
23*28613242SJonas Devlieghere                                 public IOHandlerEditline {
24*28613242SJonas Devlieghere public:
25*28613242SJonas Devlieghere   IOHandlerLuaInterpreter(Debugger &debugger)
26*28613242SJonas Devlieghere       : IOHandlerEditline(debugger, IOHandler::Type::LuaInterpreter, "lua",
27*28613242SJonas Devlieghere                           ">>> ", "..> ", true, debugger.GetUseColor(), 0,
28*28613242SJonas Devlieghere                           *this, nullptr),
29*28613242SJonas Devlieghere         m_lua() {}
30*28613242SJonas Devlieghere 
31*28613242SJonas Devlieghere   void IOHandlerInputComplete(IOHandler &io_handler,
32*28613242SJonas Devlieghere                               std::string &data) override {
33*28613242SJonas Devlieghere     if (llvm::Error error = m_lua.Run(data)) {
34*28613242SJonas Devlieghere       *GetOutputStreamFileSP() << llvm::toString(std::move(error));
35*28613242SJonas Devlieghere     }
36*28613242SJonas Devlieghere   }
37*28613242SJonas Devlieghere 
38*28613242SJonas Devlieghere private:
39*28613242SJonas Devlieghere   Lua m_lua;
40*28613242SJonas Devlieghere };
41*28613242SJonas Devlieghere 
4267de8962SJonas Devlieghere ScriptInterpreterLua::ScriptInterpreterLua(Debugger &debugger)
4367de8962SJonas Devlieghere     : ScriptInterpreter(debugger, eScriptLanguageLua) {}
4467de8962SJonas Devlieghere 
4567de8962SJonas Devlieghere ScriptInterpreterLua::~ScriptInterpreterLua() {}
4667de8962SJonas Devlieghere 
4767de8962SJonas Devlieghere bool ScriptInterpreterLua::ExecuteOneLine(llvm::StringRef command,
48*28613242SJonas Devlieghere                                           CommandReturnObject *result,
49*28613242SJonas Devlieghere                                           const ExecuteScriptOptions &options) {
50*28613242SJonas Devlieghere   Lua l;
51*28613242SJonas Devlieghere   if (llvm::Error e = l.Run(command)) {
52*28613242SJonas Devlieghere     result->AppendErrorWithFormatv(
53*28613242SJonas Devlieghere         "lua failed attempting to evaluate '{0}': {1}\n", command,
54*28613242SJonas Devlieghere         llvm::toString(std::move(e)));
5567de8962SJonas Devlieghere     return false;
5667de8962SJonas Devlieghere   }
57*28613242SJonas Devlieghere   return true;
58*28613242SJonas Devlieghere }
5967de8962SJonas Devlieghere 
6067de8962SJonas Devlieghere void ScriptInterpreterLua::ExecuteInterpreterLoop() {
61*28613242SJonas Devlieghere   static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
62*28613242SJonas Devlieghere   Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
63*28613242SJonas Devlieghere 
64*28613242SJonas Devlieghere   Debugger &debugger = m_debugger;
65*28613242SJonas Devlieghere 
66*28613242SJonas Devlieghere   // At the moment, the only time the debugger does not have an input file
67*28613242SJonas Devlieghere   // handle is when this is called directly from lua, in which case it is
68*28613242SJonas Devlieghere   // both dangerous and unnecessary (not to mention confusing) to try to embed
69*28613242SJonas Devlieghere   // a running interpreter loop inside the already running lua interpreter
70*28613242SJonas Devlieghere   // loop, so we won't do it.
71*28613242SJonas Devlieghere 
72*28613242SJonas Devlieghere   if (!debugger.GetInputFile().IsValid())
73*28613242SJonas Devlieghere     return;
74*28613242SJonas Devlieghere 
75*28613242SJonas Devlieghere   IOHandlerSP io_handler_sp(new IOHandlerLuaInterpreter(debugger));
76*28613242SJonas Devlieghere   debugger.PushIOHandler(io_handler_sp);
7767de8962SJonas Devlieghere }
7867de8962SJonas Devlieghere 
7967de8962SJonas Devlieghere void ScriptInterpreterLua::Initialize() {
8067de8962SJonas Devlieghere   static llvm::once_flag g_once_flag;
8167de8962SJonas Devlieghere 
8267de8962SJonas Devlieghere   llvm::call_once(g_once_flag, []() {
8367de8962SJonas Devlieghere     PluginManager::RegisterPlugin(GetPluginNameStatic(),
8467de8962SJonas Devlieghere                                   GetPluginDescriptionStatic(),
8567de8962SJonas Devlieghere                                   lldb::eScriptLanguageLua, CreateInstance);
8667de8962SJonas Devlieghere   });
8767de8962SJonas Devlieghere }
8867de8962SJonas Devlieghere 
8967de8962SJonas Devlieghere void ScriptInterpreterLua::Terminate() {}
9067de8962SJonas Devlieghere 
9167de8962SJonas Devlieghere lldb::ScriptInterpreterSP
9267de8962SJonas Devlieghere ScriptInterpreterLua::CreateInstance(Debugger &debugger) {
9367de8962SJonas Devlieghere   return std::make_shared<ScriptInterpreterLua>(debugger);
9467de8962SJonas Devlieghere }
9567de8962SJonas Devlieghere 
9667de8962SJonas Devlieghere lldb_private::ConstString ScriptInterpreterLua::GetPluginNameStatic() {
9767de8962SJonas Devlieghere   static ConstString g_name("script-lua");
9867de8962SJonas Devlieghere   return g_name;
9967de8962SJonas Devlieghere }
10067de8962SJonas Devlieghere 
10167de8962SJonas Devlieghere const char *ScriptInterpreterLua::GetPluginDescriptionStatic() {
10267de8962SJonas Devlieghere   return "Lua script interpreter";
10367de8962SJonas Devlieghere }
10467de8962SJonas Devlieghere 
10567de8962SJonas Devlieghere lldb_private::ConstString ScriptInterpreterLua::GetPluginName() {
10667de8962SJonas Devlieghere   return GetPluginNameStatic();
10767de8962SJonas Devlieghere }
10867de8962SJonas Devlieghere 
10967de8962SJonas Devlieghere uint32_t ScriptInterpreterLua::GetPluginVersion() { return 1; }
110