chaosbot/ChaosBot/Services/ProgrammingLanguageInterpreter/LuaProgrammingLanguageInterpreter.cs

60 lines
2.2 KiB
C#

using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using Discord.Commands;
using NLua;
namespace ChaosBot.Services.ProgrammingLanguageInterpreter
{
internal class LuaProgrammingLanguageInterpreter : IProgrammingLanguageInterpreter
{
private readonly StringBuilder _outputBuilder = new StringBuilder();
private CancellationToken _ct;
private Lua _state;
public string Interpret(CancellationToken ct, SocketCommandContext context, string content, string command)
{
LoggingFacade.Debug($"Interpreting code for {command} using Lua");
LoggingFacade.Trace($"Using CancellationToken: {ct}");
_ct = ct;
LoggingFacade.Trace("Starting Lua interpreter");
_state = new Lua();
LoggingFacade.Trace("Setting Lua debug hook");
_state.SetDebugHook(KeraLua.LuaHookMask.Line, 0);
_state.DebugHook += LuaDebugHook;
MethodInfo printMethod = GetType().GetMethod("Print", BindingFlags.NonPublic | BindingFlags.Instance);
LoggingFacade.Info($"Overwriting print function with {printMethod}");
_state["print"] = _state.RegisterFunction("print", this, printMethod);
LoggingFacade.Trace("Disabling Lua `import` function");
_state.DoString ("\nimport = function () end\n");
LoggingFacade.Trace("Running user Lua code");
_state.DoString(content, command);
LoggingFacade.Trace("Returning Lua output");
return _outputBuilder.ToString();
}
private void LuaDebugHook(object sender, NLua.Event.DebugHookEventArgs e)
{
if (_ct.IsCancellationRequested)
{
Lua l = (Lua) sender;
l.State.Error("Timeout kill");
}
}
// This is being used in the `Interpret` function to register the print function
// ReSharper disable once UnusedMember.Local
private void Print(params object[] parameters)
{
string str = string.Join("\t", from param in parameters select param == null ? string.Empty : param.ToString());
_outputBuilder.AppendLine(str);
}
}
}