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"
1028613242SJonas 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"
1428613242SJonas Devlieghere #include "lldb/Interpreter/CommandReturnObject.h"
1567de8962SJonas Devlieghere #include "lldb/Utility/Stream.h"
1667de8962SJonas Devlieghere #include "lldb/Utility/StringList.h"
1728613242SJonas Devlieghere #include "lldb/Utility/Timer.h"
1867de8962SJonas Devlieghere 
1967de8962SJonas Devlieghere using namespace lldb;
2067de8962SJonas Devlieghere using namespace lldb_private;
2167de8962SJonas Devlieghere 
2228613242SJonas Devlieghere class IOHandlerLuaInterpreter : public IOHandlerDelegate,
2328613242SJonas Devlieghere                                 public IOHandlerEditline {
2428613242SJonas Devlieghere public:
25*4164be72SJonas Devlieghere   IOHandlerLuaInterpreter(Debugger &debugger,
26*4164be72SJonas Devlieghere                           ScriptInterpreterLua &script_interpreter)
2728613242SJonas Devlieghere       : IOHandlerEditline(debugger, IOHandler::Type::LuaInterpreter, "lua",
2828613242SJonas Devlieghere                           ">>> ", "..> ", true, debugger.GetUseColor(), 0,
2928613242SJonas Devlieghere                           *this, nullptr),
30*4164be72SJonas Devlieghere         m_script_interpreter(script_interpreter) {}
3128613242SJonas Devlieghere 
3228613242SJonas Devlieghere   void IOHandlerInputComplete(IOHandler &io_handler,
3328613242SJonas Devlieghere                               std::string &data) override {
34*4164be72SJonas Devlieghere     if (llvm::Error error = m_script_interpreter.GetLua().Run(data)) {
3528613242SJonas Devlieghere       *GetOutputStreamFileSP() << llvm::toString(std::move(error));
3628613242SJonas Devlieghere     }
3728613242SJonas Devlieghere   }
3828613242SJonas Devlieghere 
3928613242SJonas Devlieghere private:
40*4164be72SJonas Devlieghere   ScriptInterpreterLua &m_script_interpreter;
4128613242SJonas Devlieghere };
4228613242SJonas Devlieghere 
4367de8962SJonas Devlieghere ScriptInterpreterLua::ScriptInterpreterLua(Debugger &debugger)
44*4164be72SJonas Devlieghere     : ScriptInterpreter(debugger, eScriptLanguageLua),
45*4164be72SJonas Devlieghere       m_lua(std::make_unique<Lua>()) {}
4667de8962SJonas Devlieghere 
4767de8962SJonas Devlieghere ScriptInterpreterLua::~ScriptInterpreterLua() {}
4867de8962SJonas Devlieghere 
4967de8962SJonas Devlieghere bool ScriptInterpreterLua::ExecuteOneLine(llvm::StringRef command,
5028613242SJonas Devlieghere                                           CommandReturnObject *result,
5128613242SJonas Devlieghere                                           const ExecuteScriptOptions &options) {
52*4164be72SJonas Devlieghere   if (llvm::Error e = m_lua->Run(command)) {
5328613242SJonas Devlieghere     result->AppendErrorWithFormatv(
5428613242SJonas Devlieghere         "lua failed attempting to evaluate '{0}': {1}\n", command,
5528613242SJonas Devlieghere         llvm::toString(std::move(e)));
5667de8962SJonas Devlieghere     return false;
5767de8962SJonas Devlieghere   }
5828613242SJonas Devlieghere   return true;
5928613242SJonas Devlieghere }
6067de8962SJonas Devlieghere 
6167de8962SJonas Devlieghere void ScriptInterpreterLua::ExecuteInterpreterLoop() {
6228613242SJonas Devlieghere   static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
6328613242SJonas Devlieghere   Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
6428613242SJonas Devlieghere 
6528613242SJonas Devlieghere   Debugger &debugger = m_debugger;
6628613242SJonas Devlieghere 
6728613242SJonas Devlieghere   // At the moment, the only time the debugger does not have an input file
6828613242SJonas Devlieghere   // handle is when this is called directly from lua, in which case it is
6928613242SJonas Devlieghere   // both dangerous and unnecessary (not to mention confusing) to try to embed
7028613242SJonas Devlieghere   // a running interpreter loop inside the already running lua interpreter
7128613242SJonas Devlieghere   // loop, so we won't do it.
7228613242SJonas Devlieghere 
7328613242SJonas Devlieghere   if (!debugger.GetInputFile().IsValid())
7428613242SJonas Devlieghere     return;
7528613242SJonas Devlieghere 
76*4164be72SJonas Devlieghere   IOHandlerSP io_handler_sp(new IOHandlerLuaInterpreter(debugger, *this));
7728613242SJonas Devlieghere   debugger.PushIOHandler(io_handler_sp);
7867de8962SJonas Devlieghere }
7967de8962SJonas Devlieghere 
8067de8962SJonas Devlieghere void ScriptInterpreterLua::Initialize() {
8167de8962SJonas Devlieghere   static llvm::once_flag g_once_flag;
8267de8962SJonas Devlieghere 
8367de8962SJonas Devlieghere   llvm::call_once(g_once_flag, []() {
8467de8962SJonas Devlieghere     PluginManager::RegisterPlugin(GetPluginNameStatic(),
8567de8962SJonas Devlieghere                                   GetPluginDescriptionStatic(),
8667de8962SJonas Devlieghere                                   lldb::eScriptLanguageLua, CreateInstance);
8767de8962SJonas Devlieghere   });
8867de8962SJonas Devlieghere }
8967de8962SJonas Devlieghere 
9067de8962SJonas Devlieghere void ScriptInterpreterLua::Terminate() {}
9167de8962SJonas Devlieghere 
9267de8962SJonas Devlieghere lldb::ScriptInterpreterSP
9367de8962SJonas Devlieghere ScriptInterpreterLua::CreateInstance(Debugger &debugger) {
9467de8962SJonas Devlieghere   return std::make_shared<ScriptInterpreterLua>(debugger);
9567de8962SJonas Devlieghere }
9667de8962SJonas Devlieghere 
9767de8962SJonas Devlieghere lldb_private::ConstString ScriptInterpreterLua::GetPluginNameStatic() {
9867de8962SJonas Devlieghere   static ConstString g_name("script-lua");
9967de8962SJonas Devlieghere   return g_name;
10067de8962SJonas Devlieghere }
10167de8962SJonas Devlieghere 
10267de8962SJonas Devlieghere const char *ScriptInterpreterLua::GetPluginDescriptionStatic() {
10367de8962SJonas Devlieghere   return "Lua script interpreter";
10467de8962SJonas Devlieghere }
10567de8962SJonas Devlieghere 
10667de8962SJonas Devlieghere lldb_private::ConstString ScriptInterpreterLua::GetPluginName() {
10767de8962SJonas Devlieghere   return GetPluginNameStatic();
10867de8962SJonas Devlieghere }
10967de8962SJonas Devlieghere 
11067de8962SJonas Devlieghere uint32_t ScriptInterpreterLua::GetPluginVersion() { return 1; }
111*4164be72SJonas Devlieghere 
112*4164be72SJonas Devlieghere Lua &ScriptInterpreterLua::GetLua() { return *m_lua; }
113