Program.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. using System.Runtime.CompilerServices;
  2. using Lua.Runtime;
  3. using Lua;
  4. using Lua.Standard;
  5. using System.Text.RegularExpressions;
  6. using System;
  7. using System.IO;
  8. using System.Text;
  9. var state = LuaState.Create();
  10. state.OpenStandardLibraries();
  11. state.Environment["escape"] = new LuaFunction("escape",
  12. (c, _) =>
  13. {
  14. var arg = c.HasArgument(0) ? c.GetArgument<string>(0) : "";
  15. return new(c.Return(Regex.Escape(arg)));
  16. });
  17. string source = "";
  18. try
  19. {
  20. source = File.ReadAllText(GetAbsolutePath("test.lua"));
  21. Console.WriteLine("Source Code " + new string('-', 50));
  22. Console.WriteLine(source);
  23. var closure = state.Load(source, "@test.lua");
  24. DebugChunk(closure.Proto, 0);
  25. Console.WriteLine("Output " + new string('-', 50));
  26. var count = await state.RootAccess.RunAsync(closure);
  27. Console.WriteLine("Result " + new string('-', 50));
  28. using var results = state.RootAccess.ReadTopValues(count);
  29. for (int i = 0; i < count; i++)
  30. {
  31. Console.WriteLine(results[i]);
  32. }
  33. Console.WriteLine("End " + new string('-', 50));
  34. }
  35. catch (Exception ex)
  36. {
  37. if (ex is LuaCompileException luaCompileException)
  38. {
  39. Console.WriteLine("CompileError " + new string('-', 50));
  40. Console.WriteLine(RustLikeExceptionHook.OnCatch(source, luaCompileException)); ;
  41. Console.WriteLine(new string('-', 55));
  42. }
  43. Console.WriteLine(ex);
  44. if (ex is LuaRuntimeException { InnerException: not null } luaEx)
  45. {
  46. Console.WriteLine("Inner Exception " + new string('-', 50));
  47. Console.WriteLine(luaEx.InnerException);
  48. }
  49. }
  50. static string GetAbsolutePath(string relativePath, [CallerFilePath] string callerFilePath = "")
  51. {
  52. return Path.Combine(Path.GetDirectoryName(callerFilePath)!, relativePath);
  53. }
  54. static void DebugChunk(Prototype chunk, int id)
  55. {
  56. Console.WriteLine($"Chunk[{id}]" + new string('=', 50));
  57. Console.WriteLine($"Parameters:{chunk.ParameterCount}");
  58. Console.WriteLine("Code " + new string('-', 50));
  59. var index = 0;
  60. foreach (var inst in chunk.Code)
  61. {
  62. Console.WriteLine($"[{index}]\t{chunk.LineInfo[index]}\t\t{inst}");
  63. index++;
  64. }
  65. Console.WriteLine("LocalVariables " + new string('-', 50));
  66. index = 0;
  67. foreach (var local in chunk.LocalVariables)
  68. {
  69. Console.WriteLine($"[{index}]\t{local.Name}\t{local.StartPc}\t{local.EndPc}");
  70. index++;
  71. }
  72. Console.WriteLine("Constants " + new string('-', 50));
  73. index = 0;
  74. foreach (var constant in chunk.Constants.ToArray())
  75. {
  76. Console.WriteLine($"[{index}]\t{Regex.Escape(constant.ToString())}");
  77. index++;
  78. }
  79. Console.WriteLine("UpValues " + new string('-', 50));
  80. index = 0;
  81. foreach (var upValue in chunk.UpValues.ToArray())
  82. {
  83. Console.WriteLine($"[{index}]\t{upValue.Name}\t{(upValue.IsLocal ? 1 : 0)}\t{upValue.Index}");
  84. index++;
  85. }
  86. Console.WriteLine();
  87. var nestedChunkId = 0;
  88. foreach (var localChunk in chunk.ChildPrototypes)
  89. {
  90. DebugChunk(localChunk, nestedChunkId);
  91. nestedChunkId++;
  92. }
  93. }
  94. public class LuaRustLikeException(string message, Exception? innerException) : Exception(message, innerException);
  95. class RustLikeExceptionHook //: ILuaCompileHook
  96. {
  97. public static string OnCatch(ReadOnlySpan<char> source, LuaCompileException exception)
  98. {
  99. var lineOffset = exception.OffSet - exception.Position.Column + 1;
  100. var length = 0;
  101. if (lineOffset < 0)
  102. {
  103. lineOffset = 0;
  104. }
  105. foreach (var c in source[lineOffset..])
  106. {
  107. if (c is '\n' or '\r')
  108. {
  109. break;
  110. }
  111. length++;
  112. }
  113. var builder = new StringBuilder();
  114. builder.AppendLine();
  115. builder.AppendLine("[error]: "+exception.MessageWithNearToken);
  116. builder.AppendLine("-->"+exception.ChunkName + ":" + exception.Position.Line + ":" + exception.Position.Column);
  117. var line = source.Slice(lineOffset, length).ToString();
  118. var lineNumString = exception.Position.Line.ToString();
  119. builder.AppendLine(new string(' ', lineNumString.Length) + " |");
  120. builder.AppendLine(lineNumString + " | " + line);
  121. builder.AppendLine(new string(' ', lineNumString.Length) + " | " +
  122. new string(' ', exception.Position.Column - 1) +
  123. "^ " + exception.MainMessage);
  124. return builder.ToString();
  125. }
  126. }