Program.cs 4.7 KB

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