Browse Source

Change: LuaState to LuaGlobalState, LuaThread to LuaState

Akeit0 4 months ago
parent
commit
cb9ac66e01
64 changed files with 1200 additions and 1156 deletions
  1. 57 27
      README.md
  2. 4 4
      sandbox/Benchmark/AddBenchmark.cs
  3. 3 3
      sandbox/Benchmark/BenchmarkCore.cs
  4. 4 4
      sandbox/Benchmark/CoroutineBenchmark.cs
  5. 2 2
      sandbox/Benchmark/HookedBenchmark.cs
  6. 10 10
      sandbox/Benchmark/InterpreterSteps.cs
  7. 24 24
      sandbox/Benchmark/NBodyBenchmark.cs
  8. 31 15
      sandbox/ConsoleApp1/Program.cs
  9. 6 6
      sandbox/ConsoleApp2/Program.cs
  10. 10 14
      sandbox/JitTest/Program.cs
  11. 1 1
      src/Lua/CodeAnalysis/Compilation/Parser.cs
  12. 1 1
      src/Lua/CodeAnalysis/Compilation/Scanner.cs
  13. 2 2
      src/Lua/CodeAnalysis/Compilation/TempBlock.cs
  14. 27 27
      src/Lua/Exceptions.cs
  15. 6 6
      src/Lua/Internal/LuaDebug.cs
  16. 10 10
      src/Lua/LuaCoroutine.cs
  17. 22 22
      src/Lua/LuaFunctionExecutionContext.cs
  18. 211 0
      src/Lua/LuaGlobalState.cs
  19. 0 15
      src/Lua/LuaMainThread.cs
  20. 176 136
      src/Lua/LuaState.cs
  21. 15 15
      src/Lua/LuaStateExtensions.cs
  22. 0 234
      src/Lua/LuaThread.cs
  23. 4 4
      src/Lua/LuaThreadExtensions.cs
  24. 3 3
      src/Lua/LuaUserThread.cs
  25. 9 9
      src/Lua/LuaValue.cs
  26. 2 2
      src/Lua/Runtime/Lease.cs
  27. 7 7
      src/Lua/Runtime/LuaClosure.cs
  28. 15 15
      src/Lua/Runtime/LuaThreadAccess.cs
  29. 24 24
      src/Lua/Runtime/LuaThreadAccessExtensions.cs
  30. 2 2
      src/Lua/Runtime/LuaValueRuntimeExtensions.cs
  31. 40 40
      src/Lua/Runtime/LuaVirtualMachine.Debug.cs
  32. 99 99
      src/Lua/Runtime/LuaVirtualMachine.cs
  33. 8 8
      src/Lua/Runtime/Tracebacks.cs
  34. 3 3
      src/Lua/Runtime/UpValue.cs
  35. 31 31
      src/Lua/Standard/BasicLibrary.cs
  36. 28 28
      src/Lua/Standard/BitwiseLibrary.cs
  37. 12 12
      src/Lua/Standard/CoroutineLibrary.cs
  38. 17 17
      src/Lua/Standard/DebugLibrary.cs
  39. 3 3
      src/Lua/Standard/FileHandle.cs
  40. 18 18
      src/Lua/Standard/IOLibrary.cs
  41. 1 1
      src/Lua/Standard/Internal/Bit32Helper.cs
  42. 3 3
      src/Lua/Standard/Internal/DateTimeHelper.cs
  43. 8 8
      src/Lua/Standard/Internal/IOHelper.cs
  44. 9 9
      src/Lua/Standard/Internal/MatchState.cs
  45. 2 2
      src/Lua/Standard/MathematicsLibrary.cs
  46. 15 15
      src/Lua/Standard/ModuleLibrary.cs
  47. 48 48
      src/Lua/Standard/OpenLibsExtensions.cs
  48. 12 12
      src/Lua/Standard/OperatingSystemLibrary.cs
  49. 27 27
      src/Lua/Standard/StringLibrary.cs
  50. 13 13
      src/Lua/Standard/TableLibrary.cs
  51. 2 2
      tests/Lua.Tests/AbstractFileTests.cs
  52. 7 7
      tests/Lua.Tests/AsyncTests.cs
  53. 13 13
      tests/Lua.Tests/CancellationTest.cs
  54. 1 1
      tests/Lua.Tests/ConditionalsTests.cs
  55. 5 5
      tests/Lua.Tests/LocalTests.cs
  56. 3 3
      tests/Lua.Tests/LoopTests.cs
  57. 12 12
      tests/Lua.Tests/LuaApiTests.cs
  58. 8 8
      tests/Lua.Tests/LuaObjectTests.cs
  59. 1 1
      tests/Lua.Tests/LuaTests.cs
  60. 11 11
      tests/Lua.Tests/MetatableTests.cs
  61. 12 12
      tests/Lua.Tests/OperatorTests.cs
  62. 36 36
      tests/Lua.Tests/PatternMatchingTests.cs
  63. 2 2
      tests/Lua.Tests/StringTests.cs
  64. 2 2
      tests/Lua.Tests/ValidationTests.cs

+ 57 - 27
README.md

@@ -12,13 +12,19 @@ English | [日本語](README_JA.md)
 
 ## Overview
 
-Lua-CSharp is a library that provides a Lua interpreter implemented in C#. By integrating Lua-CSharp, you can easily embed Lua scripts into your .NET applications.
+Lua-CSharp is a library that provides a Lua interpreter implemented in C#. By integrating Lua-CSharp, you can easily
+embed Lua scripts into your .NET applications.
 
-Lua-CSharp leverages the latest C# features, designed with low allocation and high performance in mind. It is optimized to deliver maximum performance when used for interoperation between C# and Lua in C# applications. Below is a benchmark comparison with [MoonSharp](https://github.com/moonsharp-devs/moonsharp/) and [NLua](https://github.com/NLua/NLua):
+Lua-CSharp leverages the latest C# features, designed with low allocation and high performance in mind. It is optimized
+to deliver maximum performance when used for interoperation between C# and Lua in C# applications. Below is a benchmark
+comparison with [MoonSharp](https://github.com/moonsharp-devs/moonsharp/) and [NLua](https://github.com/NLua/NLua):
 
 ![img](docs/Benchmark.png)
 
-MoonSharp generally provides good speed but incurs significant allocations due to its design. NLua, being a C-binding implementation, is fast, but introduces substantial overhead when interacting with the C# layer. Lua-CSharp, fully implemented in C#, allows for seamless interaction with C# code without additional overhead. Moreover, it operates reliably in AOT environments since it does not rely on IL generation.
+MoonSharp generally provides good speed but incurs significant allocations due to its design. NLua, being a C-binding
+implementation, is fast, but introduces substantial overhead when interacting with the C# layer. Lua-CSharp, fully
+implemented in C#, allows for seamless interaction with C# code without additional overhead. Moreover, it operates
+reliably in AOT environments since it does not rely on IL generation.
 
 ## Features
 
@@ -52,7 +58,8 @@ You can also use Lua-CSharp with Unity. For details, see the [Lua.Unity](#luauni
 
 ## Quick Start
 
-By using the `LuaState` class, you can execute Lua scripts from C#. Below is a sample code that evaluates a simple calculation written in Lua.
+By using the `LuaState` class, you can execute Lua scripts from C#. Below is a sample code that evaluates a simple
+calculation written in Lua.
 
 ```cs
 using Lua;
@@ -72,7 +79,8 @@ Console.WriteLine(results[0]);
 
 ## LuaValue
 
-Values in Lua scripts are represented by the `LuaValue` type. The value of a `LuaValue` can be read using `TryRead<T>(out T value)` or `Read<T>()`.
+Values in Lua scripts are represented by the `LuaValue` type. The value of a `LuaValue` can be read using
+`TryRead<T>(out T value)` or `Read<T>()`.
 
 ```cs
 var results = await state.DoStringAsync("return 1 + 1");
@@ -90,7 +98,7 @@ var isNil = results[0].Type == LuaValueType.Nil;
 Below is a table showing the type mapping between Lua and C#.
 
 | Lua        | C#                |
-| ---------- | ----------------- |
+|------------|-------------------|
 | `nil`      | `LuaValue.Nil`    |
 | `boolean`  | `bool`            |
 | `string`   | `string`          |
@@ -111,7 +119,8 @@ value = new LuaTable() // LuaTable ->  LuaValue
 
 ## LuaTable
 
-Lua tables are represented by the `LuaTable` type. They can be used similarly to `LuaValue[]` or `Dictionary<LuaValue, LuaValue>`.
+Lua tables are represented by the `LuaTable` type. They can be used similarly to `LuaValue[]` or
+`Dictionary<LuaValue, LuaValue>`.
 
 ```cs
 // Create a table in Lua
@@ -131,7 +140,8 @@ Console.WriteLine(table2[1]);
 
 ## Global Environment
 
-You can access Lua's global environment through `state.Environment`. This table allows for easy value exchange between Lua and C#.
+You can access Lua's global environment through `state.Environment`. This table allows for easy value exchange between
+Lua and C#.
 
 ```cs
 // Set a = 10
@@ -145,7 +155,8 @@ Console.WriteLine(results[0]);
 
 ## Standard Libraries
 
-You can use Lua's standard libraries as well. By calling `state.OpenStandardLibraries()`, the standard library tables are added to the `LuaState`.
+You can use Lua's standard libraries as well. By calling `state.OpenStandardLibraries()`, the standard library tables
+are added to the `LuaState`.
 
 ```cs
 using Lua;
@@ -160,14 +171,17 @@ var results = await state.DoStringAsync("return math.pi");
 Console.WriteLine(results[0]); // 3.141592653589793
 ```
 
-For more details on standard libraries, refer to the [Lua official manual](https://www.lua.org/manual/5.2/manual.html#6).
+For more details on standard libraries, refer to
+the [Lua official manual](https://www.lua.org/manual/5.2/manual.html#6).
 
 > [!WARNING]
-> Lua-CSharp does not support all functions of the standard libraries. For details, refer to the [Compatibility](#compatibility) section.
+> Lua-CSharp does not support all functions of the standard libraries. For details, refer to
+> the [Compatibility](#compatibility) section.
 
 ## Functions
 
-Lua functions are represented by the `LuaFunction` type. With `LuaFunction`, you can call Lua functions from C#, or define functions in C# that can be called from Lua.
+Lua functions are represented by the `LuaFunction` type. With `LuaFunction`, you can call Lua functions from C#, or
+define functions in C# that can be called from Lua.
 
 ### Calling Lua Functions from C#
 
@@ -225,11 +239,13 @@ return add(1, 2)
 ```
 
 > [!TIP]  
-> Defining functions with `LuaFunction` can be somewhat verbose. When adding multiple functions, it is recommended to use the Source Generator with the `[LuaObject]` attribute. For more details, see the [LuaObject](#luaobject) section.
+> Defining functions with `LuaFunction` can be somewhat verbose. When adding multiple functions, it is recommended to
+> use the Source Generator with the `[LuaObject]` attribute. For more details, see the [LuaObject](#luaobject) section.
 
 ## Integration with async/await
 
-`LuaFunction` operates asynchronously. Therefore, you can define a function that waits for an operation in Lua, such as the example below:
+`LuaFunction` operates asynchronously. Therefore, you can define a function that waits for an operation in Lua, such as
+the example below:
 
 ```cs
 // Define a function that waits for the given number of seconds using Task.Delay
@@ -257,7 +273,8 @@ wait(1.0) -- wait 1 sec
 print "goodbye!"
 ```
 
-This code can resume the execution of the Lua script after waiting with await, as shown in the following figure. This is very useful when writing scripts to be incorporated into games.
+This code can resume the execution of the Lua script after waiting with await, as shown in the following figure. This is
+very useful when writing scripts to be incorporated into games.
 
 ![img](docs/img1.png)
 
@@ -296,7 +313,9 @@ for (int i = 0; i < 10; i++)
 
 ## LuaObject
 
-By applying the `[LuaObject]` attribute, you can create custom classes that run within Lua. Adding this attribute to a class that you wish to use in Lua allows the Source Generator to automatically generate the code required for interaction from Lua.
+By applying the `[LuaObject]` attribute, you can create custom classes that run within Lua. Adding this attribute to a
+class that you wish to use in Lua allows the Source Generator to automatically generate the code required for
+interaction from Lua.
 
 The following is an example implementation of a wrapper class for `System.Numerics.Vector3` that can be used in Lua:
 
@@ -376,9 +395,11 @@ local v2 = v1:normalized()
 print(v2.x, v2.y, v2.z)
 ```
 
-The types of fields/properties with the `[LuaMember]` attribute, as well as the argument and return types of methods, must be either `LuaValue` or convertible to/from `LuaValue`.
+The types of fields/properties with the `[LuaMember]` attribute, as well as the argument and return types of methods,
+must be either `LuaValue` or convertible to/from `LuaValue`.
 
-Return types such as `void`, `Task/Task<T>`, `ValueTask/ValueTask<T>`, `UniTask/UniTask<T>`, and `Awaitable/Awaitable<T>` are also supported.
+Return types such as `void`, `Task/Task<T>`, `ValueTask/ValueTask<T>`, `UniTask/UniTask<T>`, and
+`Awaitable/Awaitable<T>` are also supported.
 
 If the type is not supported, the Source Generator will output a compile-time error.
 
@@ -436,7 +457,8 @@ print(v1 - v2) -- <-1, -1, -1>
 
 ## Module Loading
 
-In Lua, you can load modules using the `require` function. In regular Lua, modules are managed by searchers within the `package.searchers` function list. In Lua-CSharp, this is replaced by the `ILuaModuleLoader` interface.
+In Lua, you can load modules using the `require` function. In regular Lua, modules are managed by searchers within the
+`package.searchers` function list. In Lua-CSharp, this is replaced by the `ILuaModuleLoader` interface.
 
 ```cs
 public interface ILuaModuleLoader
@@ -446,7 +468,8 @@ public interface ILuaModuleLoader
 }
 ```
 
-You can set the `LuaState.ModuleLoader` to change how modules are loaded. By default, the `FileModuleLoader` is set to load modules from Lua files.
+You can set the `LuaState.ModuleLoader` to change how modules are loaded. By default, the `FileModuleLoader` is set to
+load modules from Lua files.
 
 You can also combine multiple loaders using `CompositeModuleLoader.Create(loader1, loader2, ...)`.
 
@@ -457,11 +480,13 @@ state.ModuleLoader = CompositeModuleLoader.Create(
 );
 ```
 
-Loaded modules are cached in the `package.loaded` table, just like regular Lua. This can be accessed via `LuaState.LoadedModules`.
+Loaded modules are cached in the `package.loaded` table, just like regular Lua. This can be accessed via
+`LuaState.LoadedModules`.
 
 ## Exception Handling
 
-Lua script parsing errors and runtime exceptions throw exceptions that inherit from `LuaException`. You can catch these to handle errors during execution.
+Lua script parsing errors and runtime exceptions throw exceptions that inherit from `LuaException`. You can catch these
+to handle errors during execution.
 
 ```cs
 try
@@ -490,9 +515,11 @@ Lua-CSharp can also be used in Unity (works with both Mono and IL2CPP).
 
 1. Install [NugetForUnity](https://github.com/GlitchEnzo/NuGetForUnity).
 
-2. Open the NuGet window by going to `NuGet > Manage NuGet Packages`, search for the `LuaCSharp` package, and install it.
+2. Open the NuGet window by going to `NuGet > Manage NuGet Packages`, search for the `LuaCSharp` package, and install
+   it.
 
-3. Open the Package Manager window by selecting `Window > Package Manager`, then click on `[+] > Add package from git URL` and enter the following URL:
+3. Open the Package Manager window by selecting `Window > Package Manager`, then click on
+   `[+] > Add package from git URL` and enter the following URL:
 
     ```
     https://github.com/AnnulusGames/Lua-CSharp.git?path=src/Lua.Unity/Assets/Lua.Unity
@@ -533,7 +560,8 @@ Lua-CSharp does not support Lua bytecode (tools like `luac` cannot be used). Onl
 
 ### Character Encoding
 
-The character encoding used in Lua-CSharp is UTF-16. Since standard Lua assumes a single-byte character encoding, string behavior differs significantly.
+The character encoding used in Lua-CSharp is UTF-16. Since standard Lua assumes a single-byte character encoding, string
+behavior differs significantly.
 
 For example, in regular Lua, the following code outputs `15`, but in Lua-CSharp, it outputs `5`.
 
@@ -546,9 +574,11 @@ All string library functions handle strings as UTF-16.
 
 ### Garbage Collection
 
-Since Lua-CSharp is implemented in C#, it relies on .NET's garbage collector. As a result, memory management behavior differs from regular Lua.
+Since Lua-CSharp is implemented in C#, it relies on .NET's garbage collector. As a result, memory management behavior
+differs from regular Lua.
 
-While `collectgarbage()` is available, it simply calls the corresponding .NET garbage collection method and may not exhibit the same behavior as C's Lua garbage collector.
+While `collectgarbage()` is available, it simply calls the corresponding .NET garbage collection method and may not
+exhibit the same behavior as C's Lua garbage collector.
 
 ## License
 

+ 4 - 4
sandbox/Benchmark/AddBenchmark.cs

@@ -20,9 +20,9 @@ public class AddBenchmark
     {
         core = new();
         core.Setup("add.lua");
-        core.LuaCSharpState.OpenStandardLibraries();
+        core.LuaGlobalCSharpState.OpenStandardLibraries();
 
-        core.LuaCSharpState.Environment["add"] = new LuaFunction("add", (context, ct) =>
+        core.LuaGlobalCSharpState.Environment["add"] = new LuaFunction("add", (context, ct) =>
         {
             var a = context.GetArgument<double>(0);
             var b = context.GetArgument<double>(1);
@@ -67,14 +67,14 @@ public class AddBenchmark
     [Benchmark(Description = "Lua-CSharp (DoString)")]
     public async Task<LuaValue> Benchmark_LuaCSharp_String()
     {
-        await core.LuaCSharpState.DoStringAsync(core.SourceText, buffer);
+        await core.LuaGlobalCSharpState.DoStringAsync(core.SourceText, buffer);
         return buffer[0];
     }
 
     [Benchmark(Description = "Lua-CSharp (DoFileAsync)")]
     public async Task<LuaValue> Benchmark_LuaCSharp_File()
     {
-        await core.LuaCSharpState.DoFileAsync(core.FilePath, buffer);
+        await core.LuaGlobalCSharpState.DoFileAsync(core.FilePath, buffer);
         return buffer[0];
     }
 }

+ 3 - 3
sandbox/Benchmark/BenchmarkCore.cs

@@ -5,13 +5,13 @@ public class BenchmarkCore : IDisposable
 {
     public NLua.Lua NLuaState => nLuaState;
     public Script MoonSharpState => moonSharpState;
-    public LuaState LuaCSharpState => luaCSharpState;
+    public LuaGlobalState LuaGlobalCSharpState => luaGlobalCSharpState;
     public string FilePath => filePath;
     public string SourceText => sourceText;
 
     NLua.Lua nLuaState = default!;
     Script moonSharpState = default!;
-    LuaState luaCSharpState = default!;
+    LuaGlobalState luaGlobalCSharpState = default!;
     string filePath = default!;
     string sourceText = default!;
 
@@ -25,7 +25,7 @@ public class BenchmarkCore : IDisposable
         nLuaState = new();
 
         // Lua-CSharp
-        luaCSharpState = LuaState.Create();
+        luaGlobalCSharpState = LuaGlobalState.Create();
 
         filePath = FileHelper.GetAbsolutePath(fileName);
         sourceText = File.ReadAllText(filePath);

+ 4 - 4
sandbox/Benchmark/CoroutineBenchmark.cs

@@ -13,8 +13,8 @@ public class CoroutineBenchmark
     public void GlobalSetup()
     {
         core.Setup("coroutine.lua");
-        core.LuaCSharpState.OpenBasicLibrary();
-        core.LuaCSharpState.OpenCoroutineLibrary();
+        core.LuaGlobalCSharpState.OpenBasicLibrary();
+        core.LuaGlobalCSharpState.OpenCoroutineLibrary();
     }
 
     [Benchmark(Description = "MoonSharp (RunString)")]
@@ -44,14 +44,14 @@ public class CoroutineBenchmark
     [Benchmark(Description = "Lua-CSharp (DoString)")]
     public async Task<LuaValue> Benchmark_LuaCSharp_String()
     {
-        await core.LuaCSharpState.DoStringAsync(core.SourceText, buffer);
+        await core.LuaGlobalCSharpState.DoStringAsync(core.SourceText, buffer);
         return buffer[0];
     }
 
     [Benchmark(Description = "Lua-CSharp (DoFileAsync)")]
     public async Task<LuaValue> Benchmark_LuaCSharp_File()
     {
-        await core.LuaCSharpState.DoFileAsync(core.FilePath, buffer);
+        await core.LuaGlobalCSharpState.DoFileAsync(core.FilePath, buffer);
         return buffer[0];
     }
 }

+ 2 - 2
sandbox/Benchmark/HookedBenchmark.cs

@@ -13,7 +13,7 @@ public class HookedBenchmark
     {
         core = new();
         core.Setup("hooked.lua");
-        core.LuaCSharpState.OpenStandardLibraries();
+        core.LuaGlobalCSharpState.OpenStandardLibraries();
     }
 
     [IterationCleanup]
@@ -34,7 +34,7 @@ public class HookedBenchmark
     [Benchmark(Description = "Lua-CSharp (DoString)")]
     public async Task<LuaValue> Benchmark_LuaCSharp_String()
     {
-        await core.LuaCSharpState.DoStringAsync(core.SourceText, buffer);
+        await core.LuaGlobalCSharpState.DoStringAsync(core.SourceText, buffer);
         return buffer[0];
     }
 }

+ 10 - 10
sandbox/Benchmark/InterpreterSteps.cs

@@ -7,7 +7,7 @@ using Lua.Standard;
 public class InterpreterSteps
 {
     string sourceText = default!;
-    LuaState state = default!;
+    LuaGlobalState globalState = default!;
     LuaClosure closure = default!;
 
     [GlobalSetup]
@@ -15,37 +15,37 @@ public class InterpreterSteps
     {
         var filePath = FileHelper.GetAbsolutePath("n-body.lua");
         sourceText = File.ReadAllText(filePath);
-        state = LuaState.Create();
-        state.OpenStandardLibraries();
-        closure = state.Load(sourceText, sourceText);
+        globalState = LuaGlobalState.Create();
+        globalState.OpenStandardLibraries();
+        closure = globalState.Load(sourceText, sourceText);
     }
 
     [IterationSetup]
     public void Setup()
     {
-        state = default!;
+        globalState = default!;
         GC.Collect();
 
-        state = LuaState.Create();
-        state.OpenStandardLibraries();
+        globalState = LuaGlobalState.Create();
+        globalState.OpenStandardLibraries();
     }
 
     [Benchmark]
     public void CreateState()
     {
-        LuaState.Create();
+        LuaGlobalState.Create();
     }
 
 
     [Benchmark]
     public LuaClosure Compile()
     {
-        return state.Load(sourceText, sourceText);
+        return globalState.Load(sourceText, sourceText);
     }
 
     [Benchmark]
     public async ValueTask RunAsync()
     {
-        await state.RootAccess.Call(closure, []);
+        await globalState.RootAccess.Call(closure, []);
     }
 }

+ 24 - 24
sandbox/Benchmark/NBodyBenchmark.cs

@@ -14,7 +14,7 @@ public class NBodyBenchmark
     {
         core = new();
         core.Setup("n-body.lua");
-        core.LuaCSharpState.OpenStandardLibraries();
+        core.LuaGlobalCSharpState.OpenStandardLibraries();
     }
 
     [IterationCleanup]
@@ -25,17 +25,17 @@ public class NBodyBenchmark
         GC.Collect();
     }
 
-    [Benchmark(Description = "MoonSharp (RunString)")]
-    public DynValue Benchmark_MoonSharp_String()
-    {
-        return core.MoonSharpState.DoString(core.SourceText);
-    }
-
-    [Benchmark(Description = "MoonSharp (RunFile)")]
-    public DynValue Benchmark_MoonSharp_File()
-    {
-        return core.MoonSharpState.DoFile(core.FilePath);
-    }
+    // [Benchmark(Description = "MoonSharp (RunString)")]
+    // public DynValue Benchmark_MoonSharp_String()
+    // {
+    //     return core.MoonSharpState.DoString(core.SourceText);
+    // }
+    //
+    // [Benchmark(Description = "MoonSharp (RunFile)")]
+    // public DynValue Benchmark_MoonSharp_File()
+    // {
+    //     return core.MoonSharpState.DoFile(core.FilePath);
+    // }
 
     [Benchmark(Description = "NLua (DoString)", Baseline = true)]
     public object[] Benchmark_NLua_String()
@@ -43,23 +43,23 @@ public class NBodyBenchmark
         return core.NLuaState.DoString(core.SourceText);
     }
 
-    [Benchmark(Description = "NLua (DoFile)")]
-    public object[] Benchmark_NLua_File()
-    {
-        return core.NLuaState.DoFile(core.FilePath);
-    }
+    // [Benchmark(Description = "NLua (DoFile)")]
+    // public object[] Benchmark_NLua_File()
+    // {
+    //     return core.NLuaState.DoFile(core.FilePath);
+    // }
 
     [Benchmark(Description = "Lua-CSharp (DoString)")]
     public async Task<LuaValue> Benchmark_LuaCSharp_String()
     {
-        await core.LuaCSharpState.DoStringAsync(core.SourceText, buffer);
+        await core.LuaGlobalCSharpState.DoStringAsync(core.SourceText, buffer);
         return buffer[0];
     }
 
-    [Benchmark(Description = "Lua-CSharp (DoFileAsync)")]
-    public async Task<LuaValue> Benchmark_LuaCSharp_File()
-    {
-        await core.LuaCSharpState.DoFileAsync(core.FilePath, buffer);
-        return buffer[0];
-    }
+    // [Benchmark(Description = "Lua-CSharp (DoFileAsync)")]
+    // public async Task<LuaValue> Benchmark_LuaCSharp_File()
+    // {
+    //     await core.LuaCSharpState.DoFileAsync(core.FilePath, buffer);
+    //     return buffer[0];
+    // }
 }

+ 31 - 15
sandbox/ConsoleApp1/Program.cs

@@ -6,24 +6,24 @@ using System.Text.RegularExpressions;
 using System;
 using System.IO;
 using System.Text;
-var state = LuaState.Create();
-state.OpenStandardLibraries();
 
+var state = LuaGlobalState.Create();
+state.OpenStandardLibraries();
 state.Environment["escape"] = new LuaFunction("escape",
     (c, _) =>
     {
         var arg = c.HasArgument(0) ? c.GetArgument<string>(0) : "";
         return new(c.Return(Regex.Escape(arg)));
     });
-string source = "";
+var source = "";
 try
 {
     source = File.ReadAllText(GetAbsolutePath("test.lua"));
 
 
-    Console.WriteLine("Source Code " + new string('-', 50));
+    //Console.WriteLine("Source Code " + new string('-', 50));
 
-    Console.WriteLine(source);
+    // Console.WriteLine(source);
 
     var closure = state.Load(source, "@test.lua");
 
@@ -31,15 +31,28 @@ try
 
     Console.WriteLine("Output " + new string('-', 50));
 
-    var count = await state.RootAccess.RunAsync(closure);
-
-    Console.WriteLine("Result " + new string('-', 50));
-    using var results = state.RootAccess.ReadTopValues(count);
-    for (int i = 0; i < count; i++)
+    //Console.Read();
+    var timer = new System.Diagnostics.Stopwatch();
+    timer.Start();
+    for (var i = 0; i < 1000; i++)
     {
-        Console.WriteLine(results[i]);
+        var count = await state.RootAccess.RunAsync(closure);
+        state.RootAccess.Pop(count);
+        if (i % 100 == 0)
+        {
+            Console.WriteLine($"Iteration {i} completed. Time elapsed: {timer.ElapsedMilliseconds} ms");
+            Thread.Sleep(100);
+        }
     }
 
+
+    // Console.WriteLine("Result " + new string('-', 50));
+    // using var results = state.RootAccess.ReadTopValues(count);
+    // for (var i = 0; i < count; i++)
+    // {
+    //     Console.WriteLine(results[i]);
+    // }
+
     Console.WriteLine("End " + new string('-', 50));
 }
 catch (Exception ex)
@@ -47,7 +60,8 @@ catch (Exception ex)
     if (ex is LuaCompileException luaCompileException)
     {
         Console.WriteLine("CompileError " + new string('-', 50));
-        Console.WriteLine(RustLikeExceptionHook.OnCatch(source, luaCompileException)); ;
+        Console.WriteLine(RustLikeExceptionHook.OnCatch(source, luaCompileException));
+        ;
         Console.WriteLine(new string('-', 55));
     }
 
@@ -124,19 +138,21 @@ class RustLikeExceptionHook //: ILuaCompileHook
         {
             lineOffset = 0;
         }
+
         foreach (var c in source[lineOffset..])
         {
             if (c is '\n' or '\r')
             {
                 break;
             }
-       
+
             length++;
         }
+
         var builder = new StringBuilder();
         builder.AppendLine();
-        builder.AppendLine("[error]: "+exception.MessageWithNearToken);
-        builder.AppendLine("-->"+exception.ChunkName + ":" + exception.Position.Line + ":" + exception.Position.Column);
+        builder.AppendLine("[error]: " + exception.MessageWithNearToken);
+        builder.AppendLine("-->" + exception.ChunkName + ":" + exception.Position.Line + ":" + exception.Position.Column);
         var line = source.Slice(lineOffset, length).ToString();
         var lineNumString = exception.Position.Line.ToString();
         builder.AppendLine(new string(' ', lineNumString.Length) + " |");

+ 6 - 6
sandbox/ConsoleApp2/Program.cs

@@ -3,16 +3,16 @@ using Lua;
 using Lua.Standard;
 using System;
 
-var state = LuaState.Create();
+var state = LuaGlobalState.Create();
 state.OpenStandardLibraries();
 {
     var closure = state.Load("return function (a,b,...)  print('a : '..a..' b :'..'args : ',...) end", "@simple");
     using var threadLease = state.MainThread.RentUserThread();
-    var access = threadLease.Thread.RootAccess;
+    var access = threadLease.State.RootAccess;
     {
         var count = await access.RunAsync(closure, 0);
         var results = access.ReadTopValues(count);
-        for (int i = 0; i < results.Length; i++)
+        for (var i = 0; i < results.Length; i++)
         {
             Console.WriteLine(results[i]);
         }
@@ -22,7 +22,7 @@ state.OpenStandardLibraries();
         access.Push("hello", "world", 1, 2, 3);
         count = await access.RunAsync(f, 5);
         results = access.ReadTopValues(count);
-        for (int i = 0; i < results.Length; i++)
+        for (var i = 0; i < results.Length; i++)
         {
             Console.WriteLine(results[i]);
         }
@@ -49,7 +49,7 @@ state.OpenStandardLibraries();
         var stack = new LuaStack();
         stack.PushRange("a", "b", "c", "d", "e");
 
-        for (int i = 0; coroutine.CanResume; i++)
+        for (var i = 0; coroutine.CanResume; i++)
         {
             if (i != 0)
             {
@@ -59,7 +59,7 @@ state.OpenStandardLibraries();
 
             await coroutine.ResumeAsync(stack);
             Console.Write("In C#:\t");
-            for (int j = 1; j < stack.Count; j++)
+            for (var j = 1; j < stack.Count; j++)
             {
                 Console.Write(stack[j]);
                 Console.Write('\t');

+ 10 - 14
sandbox/JitTest/Program.cs

@@ -11,29 +11,25 @@ using Lua.Standard;
 // dotnet run --configuration Release /p:DefineConstants="CASE_MARKER"
 // to activate the CASE_MARKER
 // JitInspect can be run in Windows and Linux (MacOS is not supported yet)
-var  luaState = LuaState.Create();
+var luaState = LuaGlobalState.Create();
 luaState.OpenStandardLibraries();
-{
-   await luaState.DoFileAsync((GetAbsolutePath("db.lua")));
-   await luaState.DoFileAsync((GetAbsolutePath("events.lua")));
-}
-
-var closure = luaState.Load(File.ReadAllBytes(GetAbsolutePath("test.lua")),"test.lua");
+var closure = luaState.Load(File.ReadAllBytes(GetAbsolutePath("test.lua")), "test.lua");
 
-for (int i = 0; i < 1000; i++)
+for (var i = 0; i < 1000; i++)
 {
-   await luaState.RootAccess.RunAsync(closure);
-   luaState.MainThread.Stack.Clear();
+    await luaState.RootAccess.RunAsync(closure);
+    luaState.MainThread.Stack.Clear();
 }
 
 var savePath = GetAbsolutePath("history");
 var thisDir = GetThisDirectoryName();
 var newJIitPath = Path.Join(thisDir, $"jit_{DateTime.Now:yyyy-MM-dd-HH-mm-ss}.txt");
-var lastJitPaths = Directory.GetFiles(thisDir).Where(x=>x.Contains("jit_"));
+var lastJitPaths = Directory.GetFiles(thisDir).Where(x => x.Contains("jit_"));
 if (!Directory.Exists(savePath))
 {
     Directory.CreateDirectory(savePath);
 }
+
 if (lastJitPaths.Any())
 {
     Console.WriteLine("Last:" + File.ReadAllLines(lastJitPaths.First())[^1]);
@@ -43,13 +39,13 @@ if (lastJitPaths.Any())
         var dest = Path.Join(savePath, Path.GetFileName(jitPath));
         File.Move(last, dest);
     }
-    
 }
+
 var method = typeof(LuaVirtualMachine).GetMethod("MoveNext", BindingFlags.Static | BindingFlags.NonPublic)!;
 using var disassembler = JitDisassembler.Create();
-var nextJitText = disassembler.Disassemble(method);
+var nextJitText = disassembler.Disassemble(method, new() { PrintInstructionAddresses = true });
 File.WriteAllText(newJIitPath, nextJitText);
-Console.WriteLine("New:" + nextJitText.Split("\n")[^1]);
+//Console.WriteLine("New:" + nextJitText.Split("\n")[^1]);
 
 
 static string GetThisDirectoryName([CallerFilePath] string callerFilePath = "")

+ 1 - 1
src/Lua/CodeAnalysis/Compilation/Parser.cs

@@ -935,7 +935,7 @@ class Parser : IPoolNode<Parser>, IDisposable
         Function = Function.CloseMainFunction();
     }
 
-    public static Prototype Parse(LuaState l, TextReader r, string name)
+    public static Prototype Parse(LuaGlobalState l, TextReader r, string name)
     {
         using var p = Get(new()
         {

+ 1 - 1
src/Lua/CodeAnalysis/Compilation/Scanner.cs

@@ -9,7 +9,7 @@ using static Constants;
 
 struct Scanner
 {
-    public LuaState L;
+    public LuaGlobalState L;
     public PooledList<char> Buffer;
     public TextReader R;
     public int Current;

+ 2 - 2
src/Lua/CodeAnalysis/Compilation/TempBlock.cs

@@ -1,9 +1,9 @@
 namespace Lua.CodeAnalysis.Compilation;
 
-readonly ref struct TempBlock(LuaState state)
+readonly ref struct TempBlock(LuaGlobalState globalState)
 {
     public void Dispose()
     {
-        state.CallCount--;
+        globalState.CallCount--;
     }
 }

+ 27 - 27
src/Lua/Exceptions.cs

@@ -88,7 +88,7 @@ interface ILuaTracebackBuildable
 
 public class LuaRuntimeException : Exception, ILuaTracebackBuildable
 {
-    public LuaRuntimeException(LuaThread? thread, Exception innerException) : base(innerException.Message, innerException)
+    public LuaRuntimeException(LuaState? thread, Exception innerException) : base(innerException.Message, innerException)
     {
         if (thread != null)
         {
@@ -100,7 +100,7 @@ public class LuaRuntimeException : Exception, ILuaTracebackBuildable
         Thread = thread;
     }
 
-    public LuaRuntimeException(LuaThread? thread, LuaValue errorObject, int level = 1)
+    public LuaRuntimeException(LuaState? thread, LuaValue errorObject, int level = 1)
     {
         if (thread != null)
         {
@@ -132,10 +132,10 @@ public class LuaRuntimeException : Exception, ILuaTracebackBuildable
         }
     }
 
-    internal LuaThread? Thread { get; private set; } = default!;
+    internal LuaState? Thread { get; private set; } = default!;
     public LuaValue ErrorObject { get; }
 
-    public static void AttemptInvalidOperation(LuaThread? thread, string op, LuaValue a, LuaValue b)
+    public static void AttemptInvalidOperation(LuaState? thread, string op, LuaValue a, LuaValue b)
     {
         var typeA = a.TypeToString();
         var typeB = b.TypeToString();
@@ -147,12 +147,12 @@ public class LuaRuntimeException : Exception, ILuaTracebackBuildable
         throw new LuaRuntimeException(thread, $"attempt to {op} a {typeA} value with a {typeB} value");
     }
 
-    public static void AttemptInvalidOperation(LuaThread? thread, string op, LuaValue a)
+    public static void AttemptInvalidOperation(LuaState? thread, string op, LuaValue a)
     {
         throw new LuaRuntimeException(thread, $"attempt to {op} a {a.TypeToString()} value");
     }
 
-    internal static void AttemptInvalidOperationOnLuaStack(LuaThread thread, string op, int lastPc, int regA, int regB)
+    internal static void AttemptInvalidOperationOnLuaStack(LuaState thread, string op, int lastPc, int regA, int regB)
     {
         var caller = thread.GetCurrentFrame();
         var luaValueA = regA < 255 ? thread.Stack[caller.Base + regA] : ((LuaClosure)caller.Function).Proto.Constants[regA - 256];
@@ -184,7 +184,7 @@ public class LuaRuntimeException : Exception, ILuaTracebackBuildable
         throw new LuaRuntimeException(thread, builder.AsSpan().ToString());
     }
 
-    internal static void AttemptInvalidOperationOnLuaStack(LuaThread thread, string op, int lastPc, int reg)
+    internal static void AttemptInvalidOperationOnLuaStack(LuaState thread, string op, int lastPc, int reg)
     {
         var caller = thread.GetCurrentFrame();
         var luaValue = reg < 255 ? thread.Stack[caller.Base + reg] : ((LuaClosure)caller.Function).Proto.Constants[reg - 256];
@@ -206,7 +206,7 @@ public class LuaRuntimeException : Exception, ILuaTracebackBuildable
         throw new LuaRuntimeException(thread, builder.AsSpan().ToString());
     }
 
-    internal static void AttemptInvalidOperationOnUpValues(LuaThread thread, string op, int reg)
+    internal static void AttemptInvalidOperationOnUpValues(LuaState thread, string op, int reg)
     {
         var caller = thread.GetCurrentFrame();
         var closure = (LuaClosure)caller.Function;
@@ -219,7 +219,7 @@ public class LuaRuntimeException : Exception, ILuaTracebackBuildable
         throw new LuaRuntimeException(thread, $"attempt to {op} a {luaValue.TypeToString()} value (upvalue '{name}')");
     }
 
-    internal static (string NameWhat, string Name) GetCurrentFunctionName(LuaThread thread)
+    internal static (string NameWhat, string Name) GetCurrentFunctionName(LuaState thread)
     {
         var current = thread.GetCurrentFrame();
         var pc = current.CallerInstructionIndex;
@@ -243,29 +243,29 @@ public class LuaRuntimeException : Exception, ILuaTracebackBuildable
         return (LuaDebug.GetFuncName(callerClosure.Proto, pc, out var name) ?? "", name ?? current.Function.Name);
     }
 
-    public static void BadArgument(LuaThread thread, int argumentId)
+    public static void BadArgument(LuaState thread, int argumentId)
     {
         BadArgument(thread, argumentId, "value expected");
     }
 
 
-    public static void BadArgument(LuaThread thread, int argumentId, LuaValueType expected, LuaValueType actual)
+    public static void BadArgument(LuaState thread, int argumentId, LuaValueType expected, LuaValueType actual)
     {
         BadArgument(thread, argumentId, $"{LuaValue.ToString(expected)} expected, got {LuaValue.ToString(actual)})");
     }
 
-    public static void BadArgument(LuaThread thread, int argumentId, LuaValueType[] expected, LuaValueType actual)
+    public static void BadArgument(LuaState thread, int argumentId, LuaValueType[] expected, LuaValueType actual)
     {
         BadArgument(thread, argumentId, $"({string.Join(" or ", expected.Select(LuaValue.ToString))} expected, got {LuaValue.ToString(actual)})");
     }
 
 
-    public static void BadArgument(LuaThread thread, int argumentId, string expected, string actual)
+    public static void BadArgument(LuaState thread, int argumentId, string expected, string actual)
     {
         BadArgument(thread, argumentId, $"({expected} expected, got {actual})");
     }
 
-    public static void BadArgument(LuaThread thread, int argumentId, string[] expected, string actual)
+    public static void BadArgument(LuaState thread, int argumentId, string[] expected, string actual)
     {
         if (expected.Length == 0)
         {
@@ -276,7 +276,7 @@ public class LuaRuntimeException : Exception, ILuaTracebackBuildable
     }
 
 
-    public static void BadArgument(LuaThread thread, int argumentId, string message)
+    public static void BadArgument(LuaState thread, int argumentId, string message)
     {
         var (nameWhat, name) = GetCurrentFunctionName(thread);
         if (nameWhat == "method")
@@ -291,12 +291,12 @@ public class LuaRuntimeException : Exception, ILuaTracebackBuildable
         throw new LuaRuntimeException(thread, $"bad argument #{argumentId} to '{name}' ({message})");
     }
 
-    public static void BadArgumentNumberIsNotInteger(LuaThread thread, int argumentId)
+    public static void BadArgumentNumberIsNotInteger(LuaState thread, int argumentId)
     {
         BadArgument(thread, argumentId, "number has no integer representation");
     }
 
-    public static void ThrowBadArgumentIfNumberIsNotInteger(LuaThread thread, int argumentId, double value)
+    public static void ThrowBadArgumentIfNumberIsNotInteger(LuaState thread, int argumentId, double value)
     {
         if (!MathEx.IsInteger(value))
         {
@@ -338,7 +338,7 @@ public class LuaRuntimeException : Exception, ILuaTracebackBuildable
                 return null;
             }
 
-            luaTraceback = new(Thread.State, callStack);
+            luaTraceback = new(Thread.GlobalState, callStack);
             Thread.ExceptionTrace.Clear();
             Thread = null;
         }
@@ -450,7 +450,7 @@ public class LuaRuntimeException : Exception, ILuaTracebackBuildable
     }
 }
 
-public class LuaAssertionException(LuaThread? traceback, string message) : LuaRuntimeException(traceback, message);
+public class LuaAssertionException(LuaState? traceback, string message) : LuaRuntimeException(traceback, message);
 
 public class LuaModuleNotFoundException(string moduleName) : Exception($"module '{moduleName}' not found");
 
@@ -471,14 +471,14 @@ public sealed class LuaCanceledException : OperationCanceledException, ILuaTrace
         }
     }
 
-    internal LuaThread? Thread { get; private set; }
+    internal LuaState? State { get; private set; }
 
-    internal LuaCanceledException(LuaThread thread, CancellationToken cancellationToken, Exception? innerException = null) : base("The operation was cancelled during execution on Lua.", innerException, cancellationToken)
+    internal LuaCanceledException(LuaState thread, CancellationToken cancellationToken, Exception? innerException = null) : base("The operation was cancelled during execution on Lua.", innerException, cancellationToken)
     {
         thread.CurrentException?.BuildOrGet();
         thread.ExceptionTrace.Clear();
         thread.CurrentException = this;
-        Thread = thread;
+        State = thread;
     }
 
 
@@ -490,17 +490,17 @@ public sealed class LuaCanceledException : OperationCanceledException, ILuaTrace
             return luaTraceback;
         }
 
-        if (Thread != null)
+        if (State != null)
         {
-            var callStack = Thread.ExceptionTrace.AsSpan();
+            var callStack = State.ExceptionTrace.AsSpan();
             if (callStack.IsEmpty)
             {
                 return null;
             }
 
-            luaTraceback = new(Thread.State, callStack);
-            Thread.ExceptionTrace.Clear();
-            Thread = null!;
+            luaTraceback = new(State.GlobalState, callStack);
+            State.ExceptionTrace.Clear();
+            State = null!;
         }
 
         return luaTraceback;

+ 6 - 6
src/Lua/Internal/LuaDebug.cs

@@ -124,11 +124,11 @@ readonly struct LuaDebug : IDisposable
         }
     }
 
-    public static LuaDebug Create(LuaState state, CallStackFrame? prevFrame, CallStackFrame? frame, LuaFunction function, int pc, ReadOnlySpan<char> what, out bool isValid)
+    public static LuaDebug Create(LuaGlobalState globalState, CallStackFrame? prevFrame, CallStackFrame? frame, LuaFunction function, int pc, ReadOnlySpan<char> what, out bool isValid)
     {
-        if (!state.DebugBufferPool.TryPop(out var buffer))
+        if (!globalState.DebugBufferPool.TryPop(out var buffer))
         {
-            buffer = new(state);
+            buffer = new(globalState);
         }
 
         isValid = buffer.GetInfo(prevFrame, frame, function, pc, what);
@@ -160,10 +160,10 @@ readonly struct LuaDebug : IDisposable
     }
 
 
-    internal class LuaDebugBuffer(LuaState state)
+    internal class LuaDebugBuffer(LuaGlobalState globalState)
     {
         internal uint version;
-        LuaState state = state;
+        LuaGlobalState globalState = globalState;
         public string? Name;
         public string? NameWhat;
         public string? What;
@@ -200,7 +200,7 @@ readonly struct LuaDebug : IDisposable
             if (version < uint.MaxValue)
             {
                 this.version++;
-                state.DebugBufferPool.Push(this);
+                globalState.DebugBufferPool.Push(this);
             }
         }
 

+ 10 - 10
src/Lua/LuaCoroutine.cs

@@ -6,14 +6,14 @@ using System.Runtime.CompilerServices;
 
 namespace Lua;
 
-public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.YieldContext>, IValueTaskSource<LuaCoroutine.ResumeContext>, IPoolNode<LuaCoroutine>
+public sealed class LuaCoroutine : LuaState, IValueTaskSource<LuaCoroutine.YieldContext>, IValueTaskSource<LuaCoroutine.ResumeContext>, IPoolNode<LuaCoroutine>
 {
     static LinkedPool<LuaCoroutine> pool;
     LuaCoroutine? nextNode;
 
     ref LuaCoroutine? IPoolNode<LuaCoroutine>.NextNode => ref nextNode;
 
-    public static LuaCoroutine Create(LuaThread parent, LuaFunction function, bool isProtectedMode)
+    public static LuaCoroutine Create(LuaState parent, LuaFunction function, bool isProtectedMode)
     {
         if (!pool.TryPop(out var result))
         {
@@ -55,10 +55,10 @@ public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.Yiel
     ManualResetValueTaskSourceCore<YieldContext> yield;
     Traceback? traceback;
 
-    internal void Init(LuaThread parent, LuaFunction function, bool isProtectedMode)
+    internal void Init(LuaState parent, LuaFunction function, bool isProtectedMode)
     {
         CoreData = ThreadCoreData.Create();
-        State = parent.State;
+        GlobalState = parent.GlobalState;
         IsProtectedMode = isProtectedMode;
         Function = function;
     }
@@ -87,18 +87,18 @@ public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.Yiel
 
     public override ValueTask<int> ResumeAsync(LuaFunctionExecutionContext context, CancellationToken cancellationToken = default)
     {
-        return ResumeAsyncCore(context.Thread.Stack, context.ArgumentCount, context.ReturnFrameBase, context.Thread, cancellationToken);
+        return ResumeAsyncCore(context.State.Stack, context.ArgumentCount, context.ReturnFrameBase, context.State, cancellationToken);
     }
 
 
     [AsyncMethodBuilder(typeof(LightAsyncValueTaskMethodBuilder<>))]
-    async ValueTask<int> ResumeAsyncCore(LuaStack stack, int argCount, int returnBase, LuaThread? baseThread, CancellationToken cancellationToken = default)
+    async ValueTask<int> ResumeAsyncCore(LuaStack stack, int argCount, int returnBase, LuaState? baseThread, CancellationToken cancellationToken = default)
     {
         if (baseThread != null)
         {
             baseThread.UnsafeSetStatus(LuaThreadStatus.Normal);
 
-            baseThread.State.ThreadStack.Push(this);
+            baseThread.GlobalState.ThreadStack.Push(this);
         }
 
         try
@@ -219,7 +219,7 @@ public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.Yiel
         {
             if (baseThread != null)
             {
-                baseThread.State.ThreadStack.Pop();
+                baseThread.GlobalState.ThreadStack.Pop();
                 baseThread.UnsafeSetStatus(LuaThreadStatus.Running);
             }
         }
@@ -232,11 +232,11 @@ public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.Yiel
 
     public override ValueTask<int> YieldAsync(LuaFunctionExecutionContext context, CancellationToken cancellationToken = default)
     {
-        return YieldAsyncCore(context.Thread.Stack, context.ArgumentCount, context.ReturnFrameBase, context.Thread, cancellationToken);
+        return YieldAsyncCore(context.State.Stack, context.ArgumentCount, context.ReturnFrameBase, context.State, cancellationToken);
     }
 
     [AsyncMethodBuilder(typeof(LightAsyncValueTaskMethodBuilder<>))]
-    async ValueTask<int> YieldAsyncCore(LuaStack stack, int argCount, int returnBase, LuaThread? baseThread, CancellationToken cancellationToken = default)
+    async ValueTask<int> YieldAsyncCore(LuaStack stack, int argCount, int returnBase, LuaState? baseThread, CancellationToken cancellationToken = default)
     {
         if (Volatile.Read(ref status) != (byte)LuaThreadStatus.Running)
         {

+ 22 - 22
src/Lua/LuaFunctionExecutionContext.cs

@@ -7,15 +7,15 @@ namespace Lua;
 [StructLayout(LayoutKind.Auto)]
 public readonly record struct LuaFunctionExecutionContext
 {
-    public LuaState State => Thread.State;
+    public LuaGlobalState GlobalState => State.GlobalState;
 
     public required LuaThreadAccess Access { get; init; }
 
-    public LuaThread Thread => Access.Thread;
+    public LuaState State => Access.State;
 
     public required int ArgumentCount { get; init; }
 
-    public int FrameBase => Thread.Stack.Count - ArgumentCount;
+    public int FrameBase => State.Stack.Count - ArgumentCount;
 
     public required int ReturnFrameBase { get; init; }
     //public object? AdditionalContext { get; init; }
@@ -24,7 +24,7 @@ public readonly record struct LuaFunctionExecutionContext
     {
         get
         {
-            var stack = Thread.Stack.AsSpan();
+            var stack = State.Stack.AsSpan();
             return stack.Slice(stack.Length - ArgumentCount);
         }
     }
@@ -64,19 +64,19 @@ public readonly record struct LuaFunctionExecutionContext
             var t = typeof(T);
             if ((t == typeof(int) || t == typeof(long)) && arg.TryReadNumber(out _))
             {
-                LuaRuntimeException.BadArgumentNumberIsNotInteger(Thread, index + 1);
+                LuaRuntimeException.BadArgumentNumberIsNotInteger(State, index + 1);
             }
             else if (LuaValue.TryGetLuaValueType(t, out var type))
             {
-                LuaRuntimeException.BadArgument(Thread, index + 1, type, arg.Type);
+                LuaRuntimeException.BadArgument(State, index + 1, type, arg.Type);
             }
             else if (arg.Type is LuaValueType.UserData or LuaValueType.LightUserData)
             {
-                LuaRuntimeException.BadArgument(Thread, index + 1, t.Name, arg.UnsafeRead<object>()?.GetType().ToString() ?? "userdata: 0");
+                LuaRuntimeException.BadArgument(State, index + 1, t.Name, arg.UnsafeRead<object>()?.GetType().ToString() ?? "userdata: 0");
             }
             else
             {
-                LuaRuntimeException.BadArgument(Thread, index + 1, t.Name, arg.TypeToString());
+                LuaRuntimeException.BadArgument(State, index + 1, t.Name, arg.TypeToString());
             }
         }
 
@@ -103,19 +103,19 @@ public readonly record struct LuaFunctionExecutionContext
             var t = typeof(T);
             if ((t == typeof(int) || t == typeof(long)) && arg.TryReadNumber(out _))
             {
-                LuaRuntimeException.BadArgumentNumberIsNotInteger(Thread, index + 1);
+                LuaRuntimeException.BadArgumentNumberIsNotInteger(State, index + 1);
             }
             else if (LuaValue.TryGetLuaValueType(t, out var type))
             {
-                LuaRuntimeException.BadArgument(Thread, index + 1, type, arg.Type);
+                LuaRuntimeException.BadArgument(State, index + 1, type, arg.Type);
             }
             else if (arg.Type is LuaValueType.UserData or LuaValueType.LightUserData)
             {
-                LuaRuntimeException.BadArgument(Thread, index + 1, t.Name, arg.UnsafeRead<object>()?.GetType().ToString() ?? "userdata: 0");
+                LuaRuntimeException.BadArgument(State, index + 1, t.Name, arg.UnsafeRead<object>()?.GetType().ToString() ?? "userdata: 0");
             }
             else
             {
-                LuaRuntimeException.BadArgument(Thread, index + 1, t.Name, arg.TypeToString());
+                LuaRuntimeException.BadArgument(State, index + 1, t.Name, arg.TypeToString());
             }
         }
 
@@ -124,13 +124,13 @@ public readonly record struct LuaFunctionExecutionContext
 
     public int Return()
     {
-        Thread.Stack.PopUntil(ReturnFrameBase);
+        State.Stack.PopUntil(ReturnFrameBase);
         return 0;
     }
 
     public int Return(LuaValue result)
     {
-        var stack = Thread.Stack;
+        var stack = State.Stack;
         stack.SetTop(ReturnFrameBase + 1);
         stack.FastGet(ReturnFrameBase) = result;
         return 1;
@@ -138,7 +138,7 @@ public readonly record struct LuaFunctionExecutionContext
 
     public int Return(LuaValue result0, LuaValue result1)
     {
-        var stack = Thread.Stack;
+        var stack = State.Stack;
         stack.SetTop(ReturnFrameBase + 2);
         stack.FastGet(ReturnFrameBase) = result0;
         stack.FastGet(ReturnFrameBase + 1) = result1;
@@ -147,7 +147,7 @@ public readonly record struct LuaFunctionExecutionContext
 
     public int Return(LuaValue result0, LuaValue result1, LuaValue result2)
     {
-        var stack = Thread.Stack;
+        var stack = State.Stack;
         stack.SetTop(ReturnFrameBase + 3);
         stack.FastGet(ReturnFrameBase) = result0;
         stack.FastGet(ReturnFrameBase + 1) = result1;
@@ -157,7 +157,7 @@ public readonly record struct LuaFunctionExecutionContext
 
     public int Return(ReadOnlySpan<LuaValue> results)
     {
-        var stack = Thread.Stack;
+        var stack = State.Stack;
         stack.EnsureCapacity(ReturnFrameBase + results.Length);
         results.CopyTo(stack.GetBuffer()[ReturnFrameBase..(ReturnFrameBase + results.Length)]);
         stack.SetTop(ReturnFrameBase + results.Length);
@@ -166,7 +166,7 @@ public readonly record struct LuaFunctionExecutionContext
 
     internal int Return(LuaValue result0, ReadOnlySpan<LuaValue> results)
     {
-        var stack = Thread.Stack;
+        var stack = State.Stack;
         stack.EnsureCapacity(ReturnFrameBase + results.Length);
         stack.SetTop(ReturnFrameBase + results.Length + 1);
         var buffer = stack.GetBuffer();
@@ -177,7 +177,7 @@ public readonly record struct LuaFunctionExecutionContext
 
     public Span<LuaValue> GetReturnBuffer(int count)
     {
-        var stack = Thread.Stack;
+        var stack = State.Stack;
         stack.SetTop(ReturnFrameBase + count);
         var buffer = stack.GetBuffer()[ReturnFrameBase..(ReturnFrameBase + count)];
         return buffer;
@@ -185,19 +185,19 @@ public readonly record struct LuaFunctionExecutionContext
 
     public CSharpClosure? GetCsClosure()
     {
-        return Thread.GetCurrentFrame().Function as CSharpClosure;
+        return State.GetCurrentFrame().Function as CSharpClosure;
     }
 
     internal void ThrowBadArgument(int index, string message)
     {
-        LuaRuntimeException.BadArgument(Thread, index, Thread.GetCurrentFrame().Function.Name, message);
+        LuaRuntimeException.BadArgument(State, index, State.GetCurrentFrame().Function.Name, message);
     }
 
     void ThrowIfArgumentNotExists(int index)
     {
         if (ArgumentCount <= index)
         {
-            LuaRuntimeException.BadArgument(Thread, index + 1);
+            LuaRuntimeException.BadArgument(State, index + 1);
         }
     }
 }

+ 211 - 0
src/Lua/LuaGlobalState.cs

@@ -0,0 +1,211 @@
+using Lua.CodeAnalysis.Compilation;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+using Lua.Internal;
+using Lua.IO;
+using Lua.Loaders;
+using Lua.Platforms;
+using Lua.Runtime;
+using Lua.Standard;
+using System.Buffers;
+using System.Text;
+
+namespace Lua;
+
+public sealed class LuaGlobalState
+{
+    // states
+    readonly LuaState mainState;
+    FastListCore<UpValue> openUpValues;
+    FastStackCore<LuaState> threadStack;
+    readonly LuaTable environment;
+    readonly LuaTable registry = new();
+    readonly UpValue envUpValue;
+
+
+    FastStackCore<LuaDebug.LuaDebugBuffer> debugBufferPool;
+
+    internal int CallCount;
+
+    internal UpValue EnvUpValue => envUpValue;
+
+    internal ref FastStackCore<LuaState> ThreadStack => ref threadStack;
+
+    internal ref FastListCore<UpValue> OpenUpValues => ref openUpValues;
+
+    internal ref FastStackCore<LuaDebug.LuaDebugBuffer> DebugBufferPool => ref debugBufferPool;
+
+    public LuaTable Environment => environment;
+
+    public LuaTable Registry => registry;
+
+    public LuaTable LoadedModules => registry[ModuleLibrary.LoadedKeyForRegistry].Read<LuaTable>();
+
+    public LuaTable PreloadModules => registry[ModuleLibrary.PreloadKeyForRegistry].Read<LuaTable>();
+
+    public LuaState MainThread => mainState;
+
+    public LuaThreadAccess RootAccess => new(mainState, 0);
+
+    public LuaPlatform Platform { get; }
+
+    public ILuaModuleLoader? ModuleLoader { get; set; }
+
+    public ILuaFileSystem FileSystem => Platform.FileSystem ?? throw new InvalidOperationException("FileSystem is not set. Please set it before access.");
+
+    public ILuaOsEnvironment OsEnvironment => Platform.OsEnvironment ?? throw new InvalidOperationException("OperatingSystem is not set. Please set it before access.");
+
+
+    public TimeProvider TimeProvider => Platform.TimeProvider ?? throw new InvalidOperationException("TimeProvider is not set. Please set it before access.");
+
+    public ILuaStandardIO StandardIO => Platform.StandardIO;
+
+    // metatables
+    LuaTable? nilMetatable;
+    LuaTable? numberMetatable;
+    LuaTable? stringMetatable;
+    LuaTable? booleanMetatable;
+    LuaTable? functionMetatable;
+    LuaTable? threadMetatable;
+
+    public static LuaGlobalState Create(LuaPlatform? platform = null)
+    {
+        LuaGlobalState globalState = new(platform ?? LuaPlatform.Default);
+        return globalState;
+    }
+
+    LuaGlobalState(LuaPlatform platform)
+    {
+        mainState = new(this);
+        environment = new();
+        envUpValue = UpValue.Closed(environment);
+        registry[ModuleLibrary.LoadedKeyForRegistry] = new LuaTable(0, 8);
+        registry[ModuleLibrary.PreloadKeyForRegistry] = new LuaTable(0, 8);
+        Platform = platform;
+    }
+
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal bool TryGetMetatable(LuaValue value, [NotNullWhen(true)] out LuaTable? result)
+    {
+        result = value.Type switch
+        {
+            LuaValueType.Nil => nilMetatable,
+            LuaValueType.Boolean => booleanMetatable,
+            LuaValueType.String => stringMetatable,
+            LuaValueType.Number => numberMetatable,
+            LuaValueType.Function => functionMetatable,
+            LuaValueType.Thread => threadMetatable,
+            LuaValueType.UserData => value.UnsafeRead<ILuaUserData>().Metatable,
+            LuaValueType.Table => value.UnsafeRead<LuaTable>().Metatable,
+            _ => null
+        };
+
+        return result != null;
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal void SetMetatable(LuaValue value, LuaTable metatable)
+    {
+        switch (value.Type)
+        {
+            case LuaValueType.Nil:
+                nilMetatable = metatable;
+                break;
+            case LuaValueType.Boolean:
+                booleanMetatable = metatable;
+                break;
+            case LuaValueType.String:
+                stringMetatable = metatable;
+                break;
+            case LuaValueType.Number:
+                numberMetatable = metatable;
+                break;
+            case LuaValueType.Function:
+                functionMetatable = metatable;
+                break;
+            case LuaValueType.Thread:
+                threadMetatable = metatable;
+                break;
+            case LuaValueType.UserData:
+                value.UnsafeRead<ILuaUserData>().Metatable = metatable;
+                break;
+            case LuaValueType.Table:
+                value.UnsafeRead<LuaTable>().Metatable = metatable;
+                break;
+        }
+    }
+
+    internal UpValue GetOrAddUpValue(LuaState thread, int registerIndex)
+    {
+        foreach (var upValue in openUpValues.AsSpan())
+        {
+            if (upValue.RegisterIndex == registerIndex && upValue.Thread == thread)
+            {
+                return upValue;
+            }
+        }
+
+        var newUpValue = UpValue.Open(thread, registerIndex);
+        openUpValues.Add(newUpValue);
+        return newUpValue;
+    }
+
+    internal void CloseUpValues(LuaState thread, int frameBase)
+    {
+        for (var i = 0; i < openUpValues.Length; i++)
+        {
+            var upValue = openUpValues[i];
+            if (upValue.Thread != thread)
+            {
+                continue;
+            }
+
+            if (upValue.RegisterIndex >= frameBase)
+            {
+                upValue.Close();
+                openUpValues.RemoveAtSwapBack(i);
+                i--;
+            }
+        }
+    }
+
+    public unsafe LuaClosure Load(ReadOnlySpan<char> chunk, string chunkName, LuaTable? environment = null)
+    {
+        Prototype prototype;
+        fixed (char* ptr = chunk)
+        {
+            prototype = Parser.Parse(this, new(ptr, chunk.Length), chunkName);
+        }
+
+        return new(MainThread, prototype, environment);
+    }
+
+    public LuaClosure Load(ReadOnlySpan<byte> chunk, string? chunkName = null, string mode = "bt", LuaTable? environment = null)
+    {
+        if (chunk.Length > 4)
+        {
+            if (chunk[0] == '\e')
+            {
+                return new(MainThread, Parser.UnDump(chunk, chunkName), environment);
+            }
+        }
+
+        chunk = BomUtility.GetEncodingFromBytes(chunk, out var encoding);
+
+        var charCount = encoding.GetCharCount(chunk);
+        var pooled = ArrayPool<char>.Shared.Rent(charCount);
+        try
+        {
+            var chars = pooled.AsSpan(0, charCount);
+            encoding.GetChars(chunk, chars);
+            chunkName ??= chars.ToString();
+
+            return Load(chars, chunkName, environment);
+        }
+        finally
+        {
+            ArrayPool<char>.Shared.Return(pooled);
+        }
+    }
+}

+ 0 - 15
src/Lua/LuaMainThread.cs

@@ -1,15 +0,0 @@
-namespace Lua;
-
-public sealed class LuaMainThread : LuaThread
-{
-    internal LuaMainThread(LuaState state)
-    {
-        State = state;
-        CoreData = ThreadCoreData.Create();
-    }
-
-    public override LuaThreadStatus GetStatus()
-    {
-        return LuaThreadStatus.Running;
-    }
-}

+ 176 - 136
src/Lua/LuaState.cs

@@ -1,211 +1,251 @@
-using Lua.CodeAnalysis.Compilation;
-using System.Diagnostics.CodeAnalysis;
 using System.Runtime.CompilerServices;
 using Lua.Internal;
-using Lua.IO;
-using Lua.Loaders;
-using Lua.Platforms;
 using Lua.Runtime;
-using Lua.Standard;
-using System.Buffers;
-using System.Text;
 
 namespace Lua;
 
-public sealed class LuaState
+public class LuaState:IDisposable
 {
-    // states
-    readonly LuaMainThread mainThread;
-    FastListCore<UpValue> openUpValues;
-    FastStackCore<LuaThread> threadStack;
-    readonly LuaTable environment;
-    readonly LuaTable registry = new();
-    readonly UpValue envUpValue;
+    protected LuaState() { }
 
+    internal LuaState(LuaGlobalState globalState)
+    {
+        GlobalState = globalState;
+        CoreData = ThreadCoreData.Create();
+    }
 
-    FastStackCore<LuaDebug.LuaDebugBuffer> debugBufferPool;
+    public virtual LuaThreadStatus GetStatus()
+    {
+        return LuaThreadStatus.Running;
+    }
 
-    internal int CallCount;
+    public virtual void UnsafeSetStatus(LuaThreadStatus status) { }
 
-    internal UpValue EnvUpValue => envUpValue;
+    public virtual ValueTask<int> ResumeAsync(LuaFunctionExecutionContext context, CancellationToken cancellationToken = default)
+    {
+        return new(context.Return(false, "cannot resume non-suspended coroutine"));
+    }
 
-    internal ref FastStackCore<LuaThread> ThreadStack => ref threadStack;
+    public virtual ValueTask<int> YieldAsync(LuaFunctionExecutionContext context, CancellationToken cancellationToken = default)
+    {
+        throw new LuaRuntimeException(context.State, "attempt to yield from outside a coroutine");
+    }
 
-    internal ref FastListCore<UpValue> OpenUpValues => ref openUpValues;
+    protected class ThreadCoreData : IPoolNode<ThreadCoreData>
+    {
+        //internal  LuaCoroutineData? coroutineData;
+        internal readonly LuaStack Stack = new();
+        internal FastStackCore<CallStackFrame> CallStack;
+
+        public void Clear()
+        {
+            Stack.Clear();
+            CallStack.Clear();
+        }
 
-    internal ref FastStackCore<LuaDebug.LuaDebugBuffer> DebugBufferPool => ref debugBufferPool;
+        static LinkedPool<ThreadCoreData> pool;
+        ThreadCoreData? nextNode;
 
-    public LuaTable Environment => environment;
+        public ref ThreadCoreData? NextNode => ref nextNode;
+
+        public static ThreadCoreData Create()
+        {
+            if (!pool.TryPop(out var result))
+            {
+                result = new();
+            }
 
-    public LuaTable Registry => registry;
+            return result;
+        }
 
-    public LuaTable LoadedModules => registry[ModuleLibrary.LoadedKeyForRegistry].Read<LuaTable>();
+        public void Release()
+        {
+            Clear();
+            pool.TryPush(this);
+        }
+    }
 
-    public LuaTable PreloadModules => registry[ModuleLibrary.PreloadKeyForRegistry].Read<LuaTable>();
+    public LuaGlobalState GlobalState { get; protected set; } = null!;
+    protected ThreadCoreData? CoreData = new();
+    internal bool IsLineHookEnabled;
+    internal BitFlags2 CallOrReturnHookMask;
+    internal bool IsInHook;
+    internal long HookCount;
+    internal int BaseHookCount;
+    internal int LastPc;
 
-    public LuaMainThread MainThread => mainThread;
+    internal int LastVersion;
+    internal int CurrentVersion;
 
-    public LuaThreadAccess RootAccess => new(mainThread, 0);
+    internal ILuaTracebackBuildable? CurrentException;
+    internal readonly ReversedStack<CallStackFrame> ExceptionTrace = new();
+    internal LuaFunction? LastCallerFunction;
 
-    public LuaPlatform Platform { get; }
+    public bool IsRunning => CallStackFrameCount != 0;
 
-    public ILuaModuleLoader? ModuleLoader { get; set; }
+    internal LuaFunction? Hook { get; set; }
 
-    public ILuaFileSystem FileSystem => Platform.FileSystem ?? throw new InvalidOperationException("FileSystem is not set. Please set it before access.");
+    public LuaStack Stack => CoreData!.Stack;
 
-    public ILuaOsEnvironment OsEnvironment => Platform.OsEnvironment ?? throw new InvalidOperationException("OperatingSystem is not set. Please set it before access.");
+    internal bool IsCallHookEnabled
+    {
+        get => CallOrReturnHookMask.Flag0;
+        set => CallOrReturnHookMask.Flag0 = value;
+    }
 
+    internal bool IsReturnHookEnabled
+    {
+        get => CallOrReturnHookMask.Flag1;
+        set => CallOrReturnHookMask.Flag1 = value;
+    }
 
-    public TimeProvider TimeProvider => Platform.TimeProvider ?? throw new InvalidOperationException("TimeProvider is not set. Please set it before access.");
+    public int CallStackFrameCount => CoreData == null ? 0 : CoreData!.CallStack.Count;
 
-    public ILuaStandardIO StandardIO => Platform.StandardIO;
+    internal LuaThreadAccess CurrentAccess => new(this, CurrentVersion);
 
-    // metatables
-    LuaTable? nilMetatable;
-    LuaTable? numberMetatable;
-    LuaTable? stringMetatable;
-    LuaTable? booleanMetatable;
-    LuaTable? functionMetatable;
-    LuaTable? threadMetatable;
+    public LuaThreadAccess RootAccess => new(this, 0);
 
-    public static LuaState Create(LuaPlatform? platform = null)
+    public ref readonly CallStackFrame GetCurrentFrame()
     {
-        LuaState state = new(platform ?? LuaPlatform.Default);
-        return state;
+        return ref CoreData!.CallStack.PeekRef();
     }
 
-    LuaState(LuaPlatform platform)
+    public ReadOnlySpan<LuaValue> GetStackValues()
     {
-        mainThread = new(this);
-        environment = new();
-        envUpValue = UpValue.Closed(environment);
-        registry[ModuleLibrary.LoadedKeyForRegistry] = new LuaTable(0, 8);
-        registry[ModuleLibrary.PreloadKeyForRegistry] = new LuaTable(0, 8);
-        Platform = platform;
+        return CoreData == null ? default : CoreData!.Stack.AsSpan();
     }
 
+    public ReadOnlySpan<CallStackFrame> GetCallStackFrames()
+    {
+        return CoreData == null ? default : CoreData!.CallStack.AsSpan();
+    }
 
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    internal bool TryGetMetatable(LuaValue value, [NotNullWhen(true)] out LuaTable? result)
+    void UpdateCurrentVersion(ref FastStackCore<CallStackFrame> callStack)
     {
-        result = value.Type switch
-        {
-            LuaValueType.Nil => nilMetatable,
-            LuaValueType.Boolean => booleanMetatable,
-            LuaValueType.String => stringMetatable,
-            LuaValueType.Number => numberMetatable,
-            LuaValueType.Function => functionMetatable,
-            LuaValueType.Thread => threadMetatable,
-            LuaValueType.UserData => value.UnsafeRead<ILuaUserData>().Metatable,
-            LuaValueType.Table => value.UnsafeRead<LuaTable>().Metatable,
-            _ => null
-        };
+        CurrentVersion = callStack.Count == 0 ? 0 : callStack.PeekRef().Version;
+    }
+
 
-        return result != null;
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal LuaThreadAccess PushCallStackFrame(in CallStackFrame frame)
+    {
+        CurrentException?.BuildOrGet();
+        CurrentException = null;
+        ref var callStack = ref CoreData!.CallStack;
+        callStack.Push(frame);
+        callStack.PeekRef().Version = CurrentVersion = ++LastVersion;
+        return new(this, CurrentVersion);
     }
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    internal void SetMetatable(LuaValue value, LuaTable metatable)
+    internal void PopCallStackFrameWithStackPop()
     {
-        switch (value.Type)
+        var coreData = CoreData!;
+        ref var callStack = ref coreData.CallStack;
+        var popFrame = callStack.Pop();
+        UpdateCurrentVersion(ref callStack);
+        if (CurrentException != null)
         {
-            case LuaValueType.Nil:
-                nilMetatable = metatable;
-                break;
-            case LuaValueType.Boolean:
-                booleanMetatable = metatable;
-                break;
-            case LuaValueType.String:
-                stringMetatable = metatable;
-                break;
-            case LuaValueType.Number:
-                numberMetatable = metatable;
-                break;
-            case LuaValueType.Function:
-                functionMetatable = metatable;
-                break;
-            case LuaValueType.Thread:
-                threadMetatable = metatable;
-                break;
-            case LuaValueType.UserData:
-                value.UnsafeRead<ILuaUserData>().Metatable = metatable;
-                break;
-            case LuaValueType.Table:
-                value.UnsafeRead<LuaTable>().Metatable = metatable;
-                break;
+            ExceptionTrace.Push(popFrame);
         }
+
+        coreData.Stack.PopUntil(popFrame.ReturnBase);
     }
 
-    internal UpValue GetOrAddUpValue(LuaThread thread, int registerIndex)
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal void PopCallStackFrameWithStackPop(int frameBase)
     {
-        foreach (var upValue in openUpValues.AsSpan())
+        var coreData = CoreData!;
+        ref var callStack = ref coreData.CallStack;
+        var popFrame = callStack.Pop();
+        UpdateCurrentVersion(ref callStack);
+        if (CurrentException != null)
         {
-            if (upValue.RegisterIndex == registerIndex && upValue.Thread == thread)
-            {
-                return upValue;
-            }
+            ExceptionTrace.Push(popFrame);
         }
 
-        var newUpValue = UpValue.Open(thread, registerIndex);
-        openUpValues.Add(newUpValue);
-        return newUpValue;
+        {
+            coreData.Stack.PopUntil(frameBase);
+        }
     }
 
-    internal void CloseUpValues(LuaThread thread, int frameBase)
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal void PopCallStackFrame()
     {
-        for (var i = 0; i < openUpValues.Length; i++)
+        var coreData = CoreData!;
+        ref var callStack = ref coreData.CallStack;
+        var popFrame = callStack.Pop();
+        UpdateCurrentVersion(ref callStack);
+        if (CurrentException != null)
         {
-            var upValue = openUpValues[i];
-            if (upValue.Thread != thread)
-            {
-                continue;
-            }
-
-            if (upValue.RegisterIndex >= frameBase)
-            {
-                upValue.Close();
-                openUpValues.RemoveAtSwapBack(i);
-                i--;
-            }
+            ExceptionTrace.Push(popFrame);
         }
     }
 
-    public unsafe LuaClosure Load(ReadOnlySpan<char> chunk, string chunkName, LuaTable? environment = null)
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    internal void PopCallStackFrameUntil(int top)
     {
-        Prototype prototype;
-        fixed (char* ptr = chunk)
+        var coreData = CoreData!;
+        ref var callStack = ref coreData.CallStack;
+        if (CurrentException != null)
         {
-            prototype = Parser.Parse(this, new(ptr, chunk.Length), chunkName);
+            ExceptionTrace.Push(callStack.AsSpan()[top..]);
         }
 
-        return new(MainThread, prototype, environment);
+        callStack.PopUntil(top);
+        UpdateCurrentVersion(ref callStack);
     }
 
-    public LuaClosure Load(ReadOnlySpan<byte> chunk, string? chunkName = null, string mode = "bt", LuaTable? environment = null)
+    public void SetHook(LuaFunction? hook, string mask, int count = 0)
     {
-        if (chunk.Length > 4)
+        if (hook is null)
         {
-            if (chunk[0] == '\e')
-            {
-                return new(MainThread, Parser.UnDump(chunk, chunkName), environment);
-            }
+            HookCount = 0;
+            BaseHookCount = 0;
+            Hook = null;
+            IsLineHookEnabled = false;
+            IsCallHookEnabled = false;
+            IsReturnHookEnabled = false;
+            return;
         }
 
-        chunk = BomUtility.GetEncodingFromBytes(chunk, out var encoding);
+        HookCount = count > 0 ? count + 1 : 0;
+        BaseHookCount = count;
 
-        var charCount = encoding.GetCharCount(chunk);
-        var pooled = ArrayPool<char>.Shared.Rent(charCount);
-        try
+        IsLineHookEnabled = mask.Contains('l');
+        IsCallHookEnabled = mask.Contains('c');
+        IsReturnHookEnabled = mask.Contains('r');
+
+        if (IsLineHookEnabled)
         {
-            var chars = pooled.AsSpan(0, charCount);
-            encoding.GetChars(chunk, chars);
-            chunkName ??= chars.ToString();
+            LastPc = CallStackFrameCount > 0 ? GetCurrentFrame().CallerInstructionIndex : -1;
+        }
 
-            return Load(chars, chunkName, environment);
+        Hook = hook;
+    }
+
+    internal void DumpStackValues()
+    {
+        var span = GetStackValues();
+        for (var i = 0; i < span.Length; i++)
+        {
+            Console.WriteLine($"LuaStack [{i}]\t{span[i]}");
         }
-        finally
+    }
+
+    public Traceback GetTraceback()
+    {
+        return new(GlobalState, GetCallStackFrames());
+    }
+    
+    public void Dispose()
+    {
+        if (CoreData!.CallStack.Count != 0)
         {
-            ArrayPool<char>.Shared.Return(pooled);
+            throw new InvalidOperationException("This thread is running! Call stack is not empty!!");
         }
+
+        CoreData.Release();
+        CoreData = null!;
     }
 }

+ 15 - 15
src/Lua/LuaStateExtensions.cs

@@ -5,42 +5,42 @@ namespace Lua;
 
 public static class LuaStateExtensions
 {
-    public static ValueTask<int> DoStringAsync(this LuaState state, string source, Memory<LuaValue> buffer, string? chunkName = null, CancellationToken cancellationToken = default)
+    public static ValueTask<int> DoStringAsync(this LuaGlobalState globalState, string source, Memory<LuaValue> buffer, string? chunkName = null, CancellationToken cancellationToken = default)
     {
-        return state.RootAccess.DoStringAsync(source, buffer, chunkName, cancellationToken);
+        return globalState.RootAccess.DoStringAsync(source, buffer, chunkName, cancellationToken);
     }
 
-    public static ValueTask<LuaValue[]> DoStringAsync(this LuaState state, string source, string? chunkName = null, CancellationToken cancellationToken = default)
+    public static ValueTask<LuaValue[]> DoStringAsync(this LuaGlobalState globalState, string source, string? chunkName = null, CancellationToken cancellationToken = default)
     {
-        return state.RootAccess.DoStringAsync(source, chunkName, cancellationToken);
+        return globalState.RootAccess.DoStringAsync(source, chunkName, cancellationToken);
     }
 
-    public static ValueTask<int> ExecuteAsync(this LuaState state, ReadOnlySpan<byte> source, Memory<LuaValue> buffer, string chunkName, CancellationToken cancellationToken = default)
+    public static ValueTask<int> ExecuteAsync(this LuaGlobalState globalState, ReadOnlySpan<byte> source, Memory<LuaValue> buffer, string chunkName, CancellationToken cancellationToken = default)
     {
-        return state.RootAccess.ExecuteAsync(source, buffer, chunkName, cancellationToken);
+        return globalState.RootAccess.ExecuteAsync(source, buffer, chunkName, cancellationToken);
     }
 
-    public static ValueTask<LuaValue[]> ExecuteAsync(this LuaState state, ReadOnlySpan<byte> source, string chunkName, CancellationToken cancellationToken = default)
+    public static ValueTask<LuaValue[]> ExecuteAsync(this LuaGlobalState globalState, ReadOnlySpan<byte> source, string chunkName, CancellationToken cancellationToken = default)
     {
-        return state.RootAccess.ExecuteAsync(source, chunkName, cancellationToken);
+        return globalState.RootAccess.ExecuteAsync(source, chunkName, cancellationToken);
     }
 
-    public static ValueTask<int> DoFileAsync(this LuaState state, string path, Memory<LuaValue> buffer, CancellationToken cancellationToken = default)
+    public static ValueTask<int> DoFileAsync(this LuaGlobalState globalState, string path, Memory<LuaValue> buffer, CancellationToken cancellationToken = default)
     {
-        return state.RootAccess.DoFileAsync(path, buffer, cancellationToken);
+        return globalState.RootAccess.DoFileAsync(path, buffer, cancellationToken);
     }
 
-    public static ValueTask<LuaValue[]> DoFileAsync(this LuaState state, string path, CancellationToken cancellationToken = default)
+    public static ValueTask<LuaValue[]> DoFileAsync(this LuaGlobalState globalState, string path, CancellationToken cancellationToken = default)
     {
-        return state.RootAccess.DoFileAsync(path, cancellationToken);
+        return globalState.RootAccess.DoFileAsync(path, cancellationToken);
     }
 
-    public static async ValueTask<LuaClosure> LoadFileAsync(this LuaState state, string fileName, string mode, LuaTable? environment, CancellationToken cancellationToken)
+    public static async ValueTask<LuaClosure> LoadFileAsync(this LuaGlobalState globalState, string fileName, string mode, LuaTable? environment, CancellationToken cancellationToken)
     {
         var name = "@" + fileName;
-        using var stream = await state.FileSystem.Open(fileName, LuaFileOpenMode.Read, cancellationToken);
+        using var stream = await globalState.FileSystem.Open(fileName, LuaFileOpenMode.Read, cancellationToken);
         var source = await stream.ReadAllAsync(cancellationToken);
-        var closure = state.Load(source, name, environment);
+        var closure = globalState.Load(source, name, environment);
 
         return closure;
     }

+ 0 - 234
src/Lua/LuaThread.cs

@@ -1,234 +0,0 @@
-using System.Runtime.CompilerServices;
-using Lua.Internal;
-using Lua.Runtime;
-
-namespace Lua;
-
-public abstract class LuaThread
-{
-    protected LuaThread() { }
-
-    public virtual LuaThreadStatus GetStatus()
-    {
-        return LuaThreadStatus.Running;
-    }
-
-    public virtual void UnsafeSetStatus(LuaThreadStatus status) { }
-
-    public virtual ValueTask<int> ResumeAsync(LuaFunctionExecutionContext context, CancellationToken cancellationToken = default)
-    {
-        return new(context.Return(false, "cannot resume non-suspended coroutine"));
-    }
-
-    public virtual ValueTask<int> YieldAsync(LuaFunctionExecutionContext context, CancellationToken cancellationToken = default)
-    {
-        throw new LuaRuntimeException(context.Thread, "attempt to yield from outside a coroutine");
-    }
-
-    protected class ThreadCoreData : IPoolNode<ThreadCoreData>
-    {
-        //internal  LuaCoroutineData? coroutineData;
-        internal readonly LuaStack Stack = new();
-        internal FastStackCore<CallStackFrame> CallStack;
-
-        public void Clear()
-        {
-            Stack.Clear();
-            CallStack.Clear();
-        }
-
-        static LinkedPool<ThreadCoreData> pool;
-        ThreadCoreData? nextNode;
-
-        public ref ThreadCoreData? NextNode => ref nextNode;
-
-        public static ThreadCoreData Create()
-        {
-            if (!pool.TryPop(out var result))
-            {
-                result = new();
-            }
-
-            return result;
-        }
-
-        public void Release()
-        {
-            Clear();
-            pool.TryPush(this);
-        }
-    }
-
-    public LuaState State { get; protected set; } = null!;
-    protected ThreadCoreData? CoreData = new();
-    internal bool IsLineHookEnabled;
-    internal BitFlags2 CallOrReturnHookMask;
-    internal bool IsInHook;
-    internal long HookCount;
-    internal int BaseHookCount;
-    internal int LastPc;
-
-    internal int LastVersion;
-    internal int CurrentVersion;
-
-    internal ILuaTracebackBuildable? CurrentException;
-    internal readonly ReversedStack<CallStackFrame> ExceptionTrace = new();
-    internal LuaFunction? LastCallerFunction;
-
-    public bool IsRunning => CallStackFrameCount != 0;
-
-    internal LuaFunction? Hook { get; set; }
-
-    public LuaStack Stack => CoreData!.Stack;
-
-    internal bool IsCallHookEnabled
-    {
-        get => CallOrReturnHookMask.Flag0;
-        set => CallOrReturnHookMask.Flag0 = value;
-    }
-
-    internal bool IsReturnHookEnabled
-    {
-        get => CallOrReturnHookMask.Flag1;
-        set => CallOrReturnHookMask.Flag1 = value;
-    }
-
-    public int CallStackFrameCount => CoreData == null ? 0 : CoreData!.CallStack.Count;
-
-    internal LuaThreadAccess CurrentAccess => new(this, CurrentVersion);
-
-    public LuaThreadAccess RootAccess => new(this, 0);
-
-    public ref readonly CallStackFrame GetCurrentFrame()
-    {
-        return ref CoreData!.CallStack.PeekRef();
-    }
-
-    public ReadOnlySpan<LuaValue> GetStackValues()
-    {
-        return CoreData == null ? default : CoreData!.Stack.AsSpan();
-    }
-
-    public ReadOnlySpan<CallStackFrame> GetCallStackFrames()
-    {
-        return CoreData == null ? default : CoreData!.CallStack.AsSpan();
-    }
-
-    void UpdateCurrentVersion(ref FastStackCore<CallStackFrame> callStack)
-    {
-        CurrentVersion = callStack.Count == 0 ? 0 : callStack.PeekRef().Version;
-    }
-
-
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    internal LuaThreadAccess PushCallStackFrame(in CallStackFrame frame)
-    {
-        CurrentException?.BuildOrGet();
-        CurrentException = null;
-        ref var callStack = ref CoreData!.CallStack;
-        callStack.Push(frame);
-        callStack.PeekRef().Version = CurrentVersion = ++LastVersion;
-        return new(this, CurrentVersion);
-    }
-
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    internal void PopCallStackFrameWithStackPop()
-    {
-        var coreData = CoreData!;
-        ref var callStack = ref coreData.CallStack;
-        var popFrame = callStack.Pop();
-        UpdateCurrentVersion(ref callStack);
-        if (CurrentException != null)
-        {
-            ExceptionTrace.Push(popFrame);
-        }
-
-        coreData.Stack.PopUntil(popFrame.ReturnBase);
-    }
-
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    internal void PopCallStackFrameWithStackPop(int frameBase)
-    {
-        var coreData = CoreData!;
-        ref var callStack = ref coreData.CallStack;
-        var popFrame = callStack.Pop();
-        UpdateCurrentVersion(ref callStack);
-        if (CurrentException != null)
-        {
-            ExceptionTrace.Push(popFrame);
-        }
-
-        {
-            coreData.Stack.PopUntil(frameBase);
-        }
-    }
-
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    internal void PopCallStackFrame()
-    {
-        var coreData = CoreData!;
-        ref var callStack = ref coreData.CallStack;
-        var popFrame = callStack.Pop();
-        UpdateCurrentVersion(ref callStack);
-        if (CurrentException != null)
-        {
-            ExceptionTrace.Push(popFrame);
-        }
-    }
-
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    internal void PopCallStackFrameUntil(int top)
-    {
-        var coreData = CoreData!;
-        ref var callStack = ref coreData.CallStack;
-        if (CurrentException != null)
-        {
-            ExceptionTrace.Push(callStack.AsSpan()[top..]);
-        }
-
-        callStack.PopUntil(top);
-        UpdateCurrentVersion(ref callStack);
-    }
-
-    public void SetHook(LuaFunction? hook, string mask, int count = 0)
-    {
-        if (hook is null)
-        {
-            HookCount = 0;
-            BaseHookCount = 0;
-            Hook = null;
-            IsLineHookEnabled = false;
-            IsCallHookEnabled = false;
-            IsReturnHookEnabled = false;
-            return;
-        }
-
-        HookCount = count > 0 ? count + 1 : 0;
-        BaseHookCount = count;
-
-        IsLineHookEnabled = mask.Contains('l');
-        IsCallHookEnabled = mask.Contains('c');
-        IsReturnHookEnabled = mask.Contains('r');
-
-        if (IsLineHookEnabled)
-        {
-            LastPc = CallStackFrameCount > 0 ? GetCurrentFrame().CallerInstructionIndex : -1;
-        }
-
-        Hook = hook;
-    }
-
-    internal void DumpStackValues()
-    {
-        var span = GetStackValues();
-        for (var i = 0; i < span.Length; i++)
-        {
-            Console.WriteLine($"LuaStack [{i}]\t{span[i]}");
-        }
-    }
-
-    public Traceback GetTraceback()
-    {
-        return new(State, GetCallStackFrames());
-    }
-}

+ 4 - 4
src/Lua/LuaThreadExtensions.cs

@@ -4,17 +4,17 @@ namespace Lua;
 
 public static class LuaThreadExtensions
 {
-    public static UserThreadLease RentUserThread(this LuaThread thread)
+    public static UserThreadLease RentUserThread(this LuaState thread)
     {
         return new(LuaUserThread.Create(thread));
     }
 
-    public static CoroutineLease RentCoroutine(this LuaThread thread, LuaFunction function, bool isProtectedMode = false)
+    public static CoroutineLease RentCoroutine(this LuaState thread, LuaFunction function, bool isProtectedMode = false)
     {
         return new(LuaCoroutine.Create(thread, function, isProtectedMode));
     }
 
-    internal static void ThrowIfCancellationRequested(this LuaThread thread, CancellationToken cancellationToken)
+    internal static void ThrowIfCancellationRequested(this LuaState thread, CancellationToken cancellationToken)
     {
         if (cancellationToken.IsCancellationRequested)
         {
@@ -23,7 +23,7 @@ public static class LuaThreadExtensions
 
         return;
 
-        static void Throw(LuaThread thread, CancellationToken cancellationToken)
+        static void Throw(LuaState thread, CancellationToken cancellationToken)
         {
             throw new LuaCanceledException(thread, cancellationToken);
         }

+ 3 - 3
src/Lua/LuaUserThread.cs

@@ -2,21 +2,21 @@
 
 namespace Lua;
 
-public sealed class LuaUserThread : LuaThread, IPoolNode<LuaUserThread>
+public sealed class LuaUserThread : LuaState, IPoolNode<LuaUserThread>
 {
     static LinkedPool<LuaUserThread> pool;
     LuaUserThread? nextNode;
 
     ref LuaUserThread? IPoolNode<LuaUserThread>.NextNode => ref nextNode;
 
-    public static LuaUserThread Create(LuaThread parent)
+    public static LuaUserThread Create(LuaState parent)
     {
         if (!pool.TryPop(out var result))
         {
             result = new();
         }
 
-        result.State = parent.State;
+        result.GlobalState = parent.GlobalState;
         result.CoreData = ThreadCoreData.Create();
 
         return result;

+ 9 - 9
src/Lua/LuaValue.cs

@@ -139,7 +139,7 @@ public readonly struct LuaValue : IEquatable<LuaValue>
                     break;
                 }
             case LuaValueType.Thread:
-                if (t == typeof(LuaThread))
+                if (t == typeof(LuaState))
                 {
                     var v = referenceValue!;
                     result = Unsafe.As<object, T>(ref v);
@@ -440,7 +440,7 @@ public readonly struct LuaValue : IEquatable<LuaValue>
             string stringValue => stringValue,
             LuaFunction luaFunction => luaFunction,
             LuaTable luaTable => luaTable,
-            LuaThread luaThread => luaThread,
+            LuaState luaThread => luaThread,
             ILuaUserData userData => FromUserData(userData),
             int intValue => intValue,
             long longValue => longValue,
@@ -502,7 +502,7 @@ public readonly struct LuaValue : IEquatable<LuaValue>
     }
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public LuaValue(LuaThread value)
+    public LuaValue(LuaState value)
     {
         Type = LuaValueType.Thread;
         referenceValue = value;
@@ -546,7 +546,7 @@ public readonly struct LuaValue : IEquatable<LuaValue>
     }
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public static implicit operator LuaValue(LuaThread value)
+    public static implicit operator LuaValue(LuaState value)
     {
         return new(value);
     }
@@ -674,7 +674,7 @@ public readonly struct LuaValue : IEquatable<LuaValue>
             result = LuaValueType.Table;
             return true;
         }
-        else if (type == typeof(LuaThread))
+        else if (type == typeof(LuaState))
         {
             result = LuaValueType.Thread;
             return true;
@@ -691,16 +691,16 @@ public readonly struct LuaValue : IEquatable<LuaValue>
 
     internal ValueTask<int> CallToStringAsync(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
-        if (this.TryGetMetamethod(context.State, Metamethods.ToString, out var metamethod))
+        if (this.TryGetMetamethod(context.GlobalState, Metamethods.ToString, out var metamethod))
         {
-            var stack = context.Thread.Stack;
+            var stack = context.State.Stack;
             stack.Push(metamethod);
             stack.Push(this);
-            return LuaVirtualMachine.Call(context.Thread, stack.Count - 2, stack.Count - 2, cancellationToken);
+            return LuaVirtualMachine.Call(context.State, stack.Count - 2, stack.Count - 2, cancellationToken);
         }
         else
         {
-            context.Thread.Stack.Push(ToString());
+            context.State.Stack.Push(ToString());
             return default;
         }
     }

+ 2 - 2
src/Lua/Runtime/Lease.cs

@@ -2,11 +2,11 @@
 
 public readonly struct UserThreadLease(LuaUserThread thread) : IDisposable
 {
-    public LuaUserThread Thread { get; } = thread;
+    public LuaUserThread State { get; } = thread;
 
     public void Dispose()
     {
-        Thread.Release();
+        State.Release();
     }
 }
 

+ 7 - 7
src/Lua/Runtime/LuaClosure.cs

@@ -8,8 +8,8 @@ public sealed class LuaClosure : LuaFunction
 {
     FastListCore<UpValue> upValues;
 
-    public LuaClosure(LuaThread thread, Prototype proto, LuaTable? environment = null)
-        : base(proto.ChunkName, static (context, ct) => LuaVirtualMachine.ExecuteClosureAsync(context.Thread, ct))
+    public LuaClosure(LuaState thread, Prototype proto, LuaTable? environment = null)
+        : base(proto.ChunkName, static (context, ct) => LuaVirtualMachine.ExecuteClosureAsync(context.State, ct))
     {
         Proto = proto;
         if (environment != null)
@@ -20,7 +20,7 @@ public sealed class LuaClosure : LuaFunction
 
         if (thread.CallStackFrameCount == 0)
         {
-            upValues.Add(thread.State.EnvUpValue);
+            upValues.Add(thread.GlobalState.EnvUpValue);
             return;
         }
 
@@ -30,7 +30,7 @@ public sealed class LuaClosure : LuaFunction
         for (var i = 0; i < proto.UpValues.Length; i++)
         {
             var description = proto.UpValues[i];
-            var upValue = GetUpValueFromDescription(thread.State, thread, description, baseIndex);
+            var upValue = GetUpValueFromDescription(thread.GlobalState, thread, description, baseIndex);
             upValues.Add(upValue);
         }
     }
@@ -62,16 +62,16 @@ public sealed class LuaClosure : LuaFunction
         upValues[index].SetValue(value);
     }
 
-    static UpValue GetUpValueFromDescription(LuaState state, LuaThread thread, UpValueDesc description, int baseIndex = 0)
+    static UpValue GetUpValueFromDescription(LuaGlobalState globalState, LuaState thread, UpValueDesc description, int baseIndex = 0)
     {
         if (description.IsLocal)
         {
             if (description is { Index: 0, Name: "_ENV" })
             {
-                return state.EnvUpValue;
+                return globalState.EnvUpValue;
             }
 
-            return state.GetOrAddUpValue(thread, baseIndex + description.Index);
+            return globalState.GetOrAddUpValue(thread, baseIndex + description.Index);
         }
 
 

+ 15 - 15
src/Lua/Runtime/LuaThreadAccess.cs

@@ -4,24 +4,24 @@ namespace Lua.Runtime;
 
 public readonly struct LuaThreadAccess
 {
-    internal LuaThreadAccess(LuaThread thread, int version)
+    internal LuaThreadAccess(LuaState thread, int version)
     {
-        Thread = thread;
+        State = thread;
         Version = version;
     }
 
-    public readonly LuaThread Thread;
+    public readonly LuaState State;
     public readonly int Version;
 
-    public bool IsValid => Version == Thread.CurrentVersion;
+    public bool IsValid => Version == State.CurrentVersion;
 
-    public LuaState State
+    public LuaGlobalState GlobalState
     {
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         get
         {
             ThrowIfInvalid();
-            return Thread.State;
+            return State.GlobalState;
         }
     }
 
@@ -31,18 +31,18 @@ public readonly struct LuaThreadAccess
         get
         {
             ThrowIfInvalid();
-            return Thread.Stack;
+            return State.Stack;
         }
     }
 
     public ValueTask<int> RunAsync(LuaFunction function, CancellationToken cancellationToken = default)
     {
-        return RunAsync(function, 0, Thread.Stack.Count, cancellationToken);
+        return RunAsync(function, 0, State.Stack.Count, cancellationToken);
     }
 
     public ValueTask<int> RunAsync(LuaFunction function, int argumentCount, CancellationToken cancellationToken = default)
     {
-        return RunAsync(function, argumentCount, Thread.Stack.Count - argumentCount, cancellationToken);
+        return RunAsync(function, argumentCount, State.Stack.Count - argumentCount, cancellationToken);
     }
 
     public async ValueTask<int> RunAsync(LuaFunction function, int argumentCount, int returnBase, CancellationToken cancellationToken = default)
@@ -53,8 +53,8 @@ public readonly struct LuaThreadAccess
             throw new ArgumentNullException(nameof(function));
         }
 
-        Thread.ThrowIfCancellationRequested(cancellationToken);
-        var thread = Thread;
+        State.ThrowIfCancellationRequested(cancellationToken);
+        var thread = State;
         var varArgumentCount = function.GetVariableArgumentCount(argumentCount);
         if (varArgumentCount != 0)
         {
@@ -82,7 +82,7 @@ public readonly struct LuaThreadAccess
         var callStackTop = thread.CallStackFrameCount;
         try
         {
-            if (Thread.CallOrReturnHookMask.Value != 0 && !Thread.IsInHook)
+            if (State.CallOrReturnHookMask.Value != 0 && !State.IsInHook)
             {
                 return await LuaVirtualMachine.ExecuteCallHook(context, cancellationToken);
             }
@@ -91,14 +91,14 @@ public readonly struct LuaThreadAccess
         }
         finally
         {
-            Thread.PopCallStackFrameUntil(callStackTop - 1);
+            State.PopCallStackFrameUntil(callStackTop - 1);
         }
     }
 
 
     internal CallStackFrame CreateCallStackFrame(LuaFunction function, int argumentCount, int returnBase, int callerInstructionIndex)
     {
-        var thread = Thread;
+        var thread = State;
         var varArgumentCount = function.GetVariableArgumentCount(argumentCount);
         if (varArgumentCount != 0)
         {
@@ -135,7 +135,7 @@ public readonly struct LuaThreadAccess
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     public void ThrowIfInvalid()
     {
-        if (Version != Thread.CurrentVersion)
+        if (Version != State.CurrentVersion)
         {
             ThrowInvalid();
         }

+ 24 - 24
src/Lua/Runtime/LuaThreadAccessExtensions.cs

@@ -9,35 +9,35 @@ public static class LuaThreadAccessAccessExtensions
     public static ValueTask<int> DoStringAsync(this LuaThreadAccess access, string source, Memory<LuaValue> results, string? chunkName = null, CancellationToken cancellationToken = default)
     {
         access.ThrowIfInvalid();
-        var closure = access.State.Load(source, chunkName ?? source);
+        var closure = access.GlobalState.Load(source, chunkName ?? source);
         return ExecuteAsync(access, closure, results, cancellationToken);
     }
 
     public static ValueTask<LuaValue[]> DoStringAsync(this LuaThreadAccess access, string source, string? chunkName = null, CancellationToken cancellationToken = default)
     {
         access.ThrowIfInvalid();
-        var closure = access.State.Load(source, chunkName ?? source);
+        var closure = access.GlobalState.Load(source, chunkName ?? source);
         return ExecuteAsync(access, closure, cancellationToken);
     }
 
     public static ValueTask<int> ExecuteAsync(this LuaThreadAccess access, ReadOnlySpan<byte> source, Memory<LuaValue> results, string chunkName, CancellationToken cancellationToken = default)
     {
         access.ThrowIfInvalid();
-        var closure = access.State.Load(source, chunkName);
+        var closure = access.GlobalState.Load(source, chunkName);
         return ExecuteAsync(access, closure, results, cancellationToken);
     }
 
     public static ValueTask<LuaValue[]> ExecuteAsync(this LuaThreadAccess access, ReadOnlySpan<byte> source, string chunkName, CancellationToken cancellationToken = default)
     {
         access.ThrowIfInvalid();
-        var closure = access.State.Load(source, chunkName);
+        var closure = access.GlobalState.Load(source, chunkName);
         return ExecuteAsync(access, closure, cancellationToken);
     }
 
     public static async ValueTask<int> DoFileAsync(this LuaThreadAccess access, string path, Memory<LuaValue> buffer, CancellationToken cancellationToken = default)
     {
         access.ThrowIfInvalid();
-        var closure = await access.State.LoadFileAsync(path, "bt", null, cancellationToken);
+        var closure = await access.GlobalState.LoadFileAsync(path, "bt", null, cancellationToken);
         var count = await access.RunAsync(closure, 0, cancellationToken);
         using var results = access.ReadTopValues(count);
         results.AsSpan()[..Math.Min(buffer.Length, results.Length)].CopyTo(buffer.Span);
@@ -46,7 +46,7 @@ public static class LuaThreadAccessAccessExtensions
 
     public static async ValueTask<LuaValue[]> DoFileAsync(this LuaThreadAccess access, string path, CancellationToken cancellationToken = default)
     {
-        var closure = await access.State.LoadFileAsync(path, "bt", null, cancellationToken);
+        var closure = await access.GlobalState.LoadFileAsync(path, "bt", null, cancellationToken);
         var count = await access.RunAsync(closure, 0, cancellationToken);
         using var results = access.ReadTopValues(count);
         return results.AsSpan().ToArray();
@@ -108,7 +108,7 @@ public static class LuaThreadAccessAccessExtensions
         }
 
         access.ThrowIfInvalid();
-        return LuaVirtualMachine.ExecuteBinaryOperationMetaMethod(access.Thread, x, y, OpCode.Add, cancellationToken);
+        return LuaVirtualMachine.ExecuteBinaryOperationMetaMethod(access.State, x, y, OpCode.Add, cancellationToken);
     }
 
     public static ValueTask<LuaValue> Sub(this LuaThreadAccess access, LuaValue x, LuaValue y, CancellationToken cancellationToken = default)
@@ -119,7 +119,7 @@ public static class LuaThreadAccessAccessExtensions
         }
 
         access.ThrowIfInvalid();
-        return LuaVirtualMachine.ExecuteBinaryOperationMetaMethod(access.Thread, x, y, OpCode.Sub, cancellationToken);
+        return LuaVirtualMachine.ExecuteBinaryOperationMetaMethod(access.State, x, y, OpCode.Sub, cancellationToken);
     }
 
     public static ValueTask<LuaValue> Mul(this LuaThreadAccess access, LuaValue x, LuaValue y, CancellationToken cancellationToken = default)
@@ -130,7 +130,7 @@ public static class LuaThreadAccessAccessExtensions
         }
 
         access.ThrowIfInvalid();
-        return LuaVirtualMachine.ExecuteBinaryOperationMetaMethod(access.Thread, x, y, OpCode.Mul, cancellationToken);
+        return LuaVirtualMachine.ExecuteBinaryOperationMetaMethod(access.State, x, y, OpCode.Mul, cancellationToken);
     }
 
     public static ValueTask<LuaValue> Div(this LuaThreadAccess access, LuaValue x, LuaValue y, CancellationToken cancellationToken = default)
@@ -141,7 +141,7 @@ public static class LuaThreadAccessAccessExtensions
         }
 
         access.ThrowIfInvalid();
-        return LuaVirtualMachine.ExecuteBinaryOperationMetaMethod(access.Thread, x, y, OpCode.Div, cancellationToken);
+        return LuaVirtualMachine.ExecuteBinaryOperationMetaMethod(access.State, x, y, OpCode.Div, cancellationToken);
     }
 
     public static ValueTask<LuaValue> Mod(this LuaThreadAccess access, LuaValue x, LuaValue y, CancellationToken cancellationToken = default)
@@ -152,7 +152,7 @@ public static class LuaThreadAccessAccessExtensions
         }
 
         access.ThrowIfInvalid();
-        return LuaVirtualMachine.ExecuteBinaryOperationMetaMethod(access.Thread, x, y, OpCode.Mod, cancellationToken);
+        return LuaVirtualMachine.ExecuteBinaryOperationMetaMethod(access.State, x, y, OpCode.Mod, cancellationToken);
     }
 
     public static ValueTask<LuaValue> Pow(this LuaThreadAccess access, LuaValue x, LuaValue y, CancellationToken cancellationToken = default)
@@ -163,7 +163,7 @@ public static class LuaThreadAccessAccessExtensions
         }
 
         access.ThrowIfInvalid();
-        return LuaVirtualMachine.ExecuteBinaryOperationMetaMethod(access.Thread, x, y, OpCode.Pow, cancellationToken);
+        return LuaVirtualMachine.ExecuteBinaryOperationMetaMethod(access.State, x, y, OpCode.Pow, cancellationToken);
     }
 
 
@@ -175,7 +175,7 @@ public static class LuaThreadAccessAccessExtensions
         }
 
         access.ThrowIfInvalid();
-        return LuaVirtualMachine.ExecuteUnaryOperationMetaMethod(access.Thread, value, OpCode.Unm, cancellationToken);
+        return LuaVirtualMachine.ExecuteUnaryOperationMetaMethod(access.State, value, OpCode.Unm, cancellationToken);
     }
 
     public static ValueTask<LuaValue> Len(this LuaThreadAccess access, LuaValue value, CancellationToken cancellationToken = default)
@@ -191,7 +191,7 @@ public static class LuaThreadAccessAccessExtensions
         }
 
         access.ThrowIfInvalid();
-        return LuaVirtualMachine.ExecuteUnaryOperationMetaMethod(access.Thread, value, OpCode.Len, cancellationToken);
+        return LuaVirtualMachine.ExecuteUnaryOperationMetaMethod(access.State, value, OpCode.Len, cancellationToken);
     }
 
 
@@ -209,7 +209,7 @@ public static class LuaThreadAccessAccessExtensions
         }
 
         access.ThrowIfInvalid();
-        return LuaVirtualMachine.ExecuteCompareOperationMetaMethod(access.Thread, x, y, OpCode.Lt, cancellationToken);
+        return LuaVirtualMachine.ExecuteCompareOperationMetaMethod(access.State, x, y, OpCode.Lt, cancellationToken);
     }
 
     public static ValueTask<bool> LessThanOrEquals(this LuaThreadAccess access, LuaValue x, LuaValue y, CancellationToken cancellationToken = default)
@@ -226,7 +226,7 @@ public static class LuaThreadAccessAccessExtensions
         }
 
         access.ThrowIfInvalid();
-        return LuaVirtualMachine.ExecuteCompareOperationMetaMethod(access.Thread, x, y, OpCode.Le, cancellationToken);
+        return LuaVirtualMachine.ExecuteCompareOperationMetaMethod(access.State, x, y, OpCode.Le, cancellationToken);
     }
 
     public static ValueTask<bool> Equals(this LuaThreadAccess access, LuaValue x, LuaValue y, CancellationToken cancellationToken = default)
@@ -237,7 +237,7 @@ public static class LuaThreadAccessAccessExtensions
         }
 
         access.ThrowIfInvalid();
-        return LuaVirtualMachine.ExecuteCompareOperationMetaMethod(access.Thread, x, y, OpCode.Eq, cancellationToken);
+        return LuaVirtualMachine.ExecuteCompareOperationMetaMethod(access.State, x, y, OpCode.Eq, cancellationToken);
     }
 
 
@@ -252,7 +252,7 @@ public static class LuaThreadAccessAccessExtensions
         }
 
         access.ThrowIfInvalid();
-        return await LuaVirtualMachine.ExecuteGetTableSlowPath(access.Thread, table, key, cancellationToken);
+        return await LuaVirtualMachine.ExecuteGetTableSlowPath(access.State, table, key, cancellationToken);
     }
 
     public static ValueTask SetTable(this LuaThreadAccess access, LuaValue table, LuaValue key, LuaValue value, CancellationToken cancellationToken = default)
@@ -263,7 +263,7 @@ public static class LuaThreadAccessAccessExtensions
         {
             if (double.IsNaN(numB))
             {
-                throw new LuaRuntimeException(access.Thread, "table index is NaN");
+                throw new LuaRuntimeException(access.State, "table index is NaN");
             }
         }
 
@@ -278,7 +278,7 @@ public static class LuaThreadAccessAccessExtensions
             }
         }
 
-        return LuaVirtualMachine.ExecuteSetTableSlowPath(access.Thread, table, key, value, cancellationToken);
+        return LuaVirtualMachine.ExecuteSetTableSlowPath(access.State, table, key, value, cancellationToken);
     }
 
     public static ValueTask<LuaValue> Concat(this LuaThreadAccess access, ReadOnlySpan<LuaValue> values, CancellationToken cancellationToken = default)
@@ -291,19 +291,19 @@ public static class LuaThreadAccessAccessExtensions
     public static ValueTask<LuaValue> Concat(this LuaThreadAccess access, int concatCount, CancellationToken cancellationToken = default)
     {
         access.ThrowIfInvalid();
-        return LuaVirtualMachine.Concat(access.Thread, concatCount, cancellationToken);
+        return LuaVirtualMachine.Concat(access.State, concatCount, cancellationToken);
     }
 
     public static ValueTask<int> Call(this LuaThreadAccess access, int funcIndex, int returnBase, CancellationToken cancellationToken = default)
     {
         access.ThrowIfInvalid();
-        return LuaVirtualMachine.Call(access.Thread, funcIndex, returnBase, cancellationToken);
+        return LuaVirtualMachine.Call(access.State, funcIndex, returnBase, cancellationToken);
     }
 
     public static ValueTask<LuaValue[]> Call(this LuaThreadAccess access, LuaValue function, ReadOnlySpan<LuaValue> arguments, CancellationToken cancellationToken = default)
     {
         access.ThrowIfInvalid();
-        var thread = access.Thread;
+        var thread = access.State;
         var funcIndex = thread.Stack.Count;
         thread.Stack.Push(function);
         thread.Stack.PushRange(arguments);
@@ -311,7 +311,7 @@ public static class LuaThreadAccessAccessExtensions
 
         static async ValueTask<LuaValue[]> Impl(LuaThreadAccess access, int funcIndex, CancellationToken cancellationToken)
         {
-            await LuaVirtualMachine.Call(access.Thread, funcIndex, funcIndex, cancellationToken);
+            await LuaVirtualMachine.Call(access.State, funcIndex, funcIndex, cancellationToken);
             var count = access.Stack.Count - funcIndex;
             using var results = access.ReadTopValues(count);
             return results.AsSpan().ToArray();

+ 2 - 2
src/Lua/Runtime/LuaValueRuntimeExtensions.cs

@@ -5,10 +5,10 @@ namespace Lua.Runtime;
 static class LuaRuntimeExtensions
 {
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public static bool TryGetMetamethod(this LuaValue value, LuaState state, string methodName, out LuaValue result)
+    public static bool TryGetMetamethod(this LuaValue value, LuaGlobalState globalState, string methodName, out LuaValue result)
     {
         result = default;
-        return state.TryGetMetatable(value, out var metatable) &&
+        return globalState.TryGetMetatable(value, out var metatable) &&
                metatable.TryGetValue(methodName, out result);
     }
 

+ 40 - 40
src/Lua/Runtime/LuaVirtualMachine.Debug.cs

@@ -12,7 +12,7 @@ public static partial class LuaVirtualMachine
         {
             if (r.Result == 0)
             {
-                context.Thread.PopCallStackFrameWithStackPop();
+                context.State.PopCallStackFrameWithStackPop();
             }
 
             return false;
@@ -27,48 +27,48 @@ public static partial class LuaVirtualMachine
             var countHookIsDone = false;
             var pc = context.Pc;
             var prototype = context.Prototype;
-            if (context.Thread.HookCount == 0)
+            if (context.State.HookCount == 0)
             {
-                context.Thread.HookCount = context.Thread.BaseHookCount + 1;
+                context.State.HookCount = context.State.BaseHookCount + 1;
 
-                var hook = context.Thread.Hook!;
+                var hook = context.State.Hook!;
 
-                var stack = context.Thread.Stack;
+                var stack = context.State.Stack;
                 var top = stack.Count;
                 stack.Push("count");
                 stack.Push(LuaValue.Nil);
-                context.Thread.IsInHook = true;
-                var frame = context.Thread.CurrentAccess.CreateCallStackFrame(hook, 2, top, pc);
-                var access = context.Thread.PushCallStackFrame(frame);
+                context.State.IsInHook = true;
+                var frame = context.State.CurrentAccess.CreateCallStackFrame(hook, 2, top, pc);
+                var access = context.State.PushCallStackFrame(frame);
                 LuaFunctionExecutionContext funcContext = new() { Access = access, ArgumentCount = stack.Count - frame.Base, ReturnFrameBase = frame.ReturnBase };
                 await hook.Func(funcContext, context.CancellationToken);
-                context.Thread.IsInHook = false;
+                context.State.IsInHook = false;
 
                 countHookIsDone = true;
             }
 
             context.ThrowIfCancellationRequested();
-            if (context.Thread.IsLineHookEnabled)
+            if (context.State.IsLineHookEnabled)
             {
                 var sourcePositions = prototype.LineInfo;
                 var line = sourcePositions[pc];
 
-                if (countHookIsDone || pc == 0 || context.Thread.LastPc < 0 || pc <= context.Thread.LastPc || sourcePositions[context.Thread.LastPc] != line)
+                if (countHookIsDone || pc == 0 || context.State.LastPc < 0 || pc <= context.State.LastPc || sourcePositions[context.State.LastPc] != line)
                 {
                     if (countHookIsDone)
                     {
-                        context.Thread.PopCallStackFrameWithStackPop();
+                        context.State.PopCallStackFrameWithStackPop();
                     }
 
 
-                    var hook = context.Thread.Hook!;
-                    var stack = context.Thread.Stack;
+                    var hook = context.State.Hook!;
+                    var stack = context.State.Stack;
                     var top = stack.Count;
                     stack.Push("line");
                     stack.Push(line);
-                    context.Thread.IsInHook = true;
-                    var frame = context.Thread.CurrentAccess.CreateCallStackFrame(hook, 2, top, pc);
-                    var access = context.Thread.PushCallStackFrame(frame);
+                    context.State.IsInHook = true;
+                    var frame = context.State.CurrentAccess.CreateCallStackFrame(hook, 2, top, pc);
+                    var access = context.State.PushCallStackFrame(frame);
                     LuaFunctionExecutionContext funcContext = new() { Access = access, ArgumentCount = stack.Count - frame.Base, ReturnFrameBase = frame.ReturnBase };
                     try
                     {
@@ -76,14 +76,14 @@ public static partial class LuaVirtualMachine
                     }
                     finally
                     {
-                        context.Thread.IsInHook = false;
+                        context.State.IsInHook = false;
                     }
 
-                    context.Thread.LastPc = pc;
+                    context.State.LastPc = pc;
                     return 0;
                 }
 
-                context.Thread.LastPc = pc;
+                context.State.LastPc = pc;
             }
 
             if (countHookIsDone)
@@ -98,23 +98,23 @@ public static partial class LuaVirtualMachine
     [MethodImpl(MethodImplOptions.NoInlining)]
     static ValueTask<int> ExecuteCallHook(VirtualMachineExecutionContext context, in CallStackFrame frame, int arguments, bool isTailCall = false)
     {
-        return ExecuteCallHook(new() { Access = context.Thread.CurrentAccess, ArgumentCount = arguments, ReturnFrameBase = frame.ReturnBase }, context.CancellationToken, isTailCall);
+        return ExecuteCallHook(new() { Access = context.State.CurrentAccess, ArgumentCount = arguments, ReturnFrameBase = frame.ReturnBase }, context.CancellationToken, isTailCall);
     }
 
     internal static async ValueTask<int> ExecuteCallHook(LuaFunctionExecutionContext context, CancellationToken cancellationToken, bool isTailCall = false)
     {
         var argCount = context.ArgumentCount;
-        var hook = context.Thread.Hook!;
-        var stack = context.Thread.Stack;
-        if (context.Thread.IsCallHookEnabled)
+        var hook = context.State.Hook!;
+        var stack = context.State.Stack;
+        if (context.State.IsCallHookEnabled)
         {
             var top = stack.Count;
             stack.Push(isTailCall ? "tail call" : "call");
 
             stack.Push(LuaValue.Nil);
-            context.Thread.IsInHook = true;
-            var frame = context.Thread.CurrentAccess.CreateCallStackFrame(hook, 2, top, 0);
-            var access = context.Thread.PushCallStackFrame(frame);
+            context.State.IsInHook = true;
+            var frame = context.State.CurrentAccess.CreateCallStackFrame(hook, 2, top, 0);
+            var access = context.State.PushCallStackFrame(frame);
             LuaFunctionExecutionContext funcContext = new() { Access = access, ArgumentCount = stack.Count - frame.Base, ReturnFrameBase = frame.ReturnBase };
             try
             {
@@ -122,39 +122,39 @@ public static partial class LuaVirtualMachine
             }
             finally
             {
-                context.Thread.IsInHook = false;
-                context.Thread.PopCallStackFrameWithStackPop();
+                context.State.IsInHook = false;
+                context.State.PopCallStackFrameWithStackPop();
             }
         }
 
-        context.Thread.ThrowIfCancellationRequested(cancellationToken);
+        context.State.ThrowIfCancellationRequested(cancellationToken);
 
         {
-            var frame = context.Thread.GetCurrentFrame();
-            var task = frame.Function.Func(new() { Access = context.Thread.CurrentAccess, ArgumentCount = argCount, ReturnFrameBase = frame.ReturnBase }, cancellationToken);
+            var frame = context.State.GetCurrentFrame();
+            var task = frame.Function.Func(new() { Access = context.State.CurrentAccess, ArgumentCount = argCount, ReturnFrameBase = frame.ReturnBase }, cancellationToken);
             var r = await task;
-            if (isTailCall || !context.Thread.IsReturnHookEnabled)
+            if (isTailCall || !context.State.IsReturnHookEnabled)
             {
                 return r;
             }
 
-            context.Thread.ThrowIfCancellationRequested(cancellationToken);
+            context.State.ThrowIfCancellationRequested(cancellationToken);
             var top = stack.Count;
             stack.Push("return");
             stack.Push(LuaValue.Nil);
-            context.Thread.IsInHook = true;
-            frame = context.Thread.CurrentAccess.CreateCallStackFrame(hook, 2, top, 0);
-            var access = context.Thread.PushCallStackFrame(frame);
+            context.State.IsInHook = true;
+            frame = context.State.CurrentAccess.CreateCallStackFrame(hook, 2, top, 0);
+            var access = context.State.PushCallStackFrame(frame);
             LuaFunctionExecutionContext funcContext = new() { Access = access, ArgumentCount = stack.Count - frame.Base, ReturnFrameBase = frame.ReturnBase };
             try
             {
-                context.Thread.IsInHook = true;
+                context.State.IsInHook = true;
                 await hook.Func(funcContext, cancellationToken);
             }
             finally
             {
-                context.Thread.IsInHook = false;
-                context.Thread.PopCallStackFrameWithStackPop();
+                context.State.IsInHook = false;
+                context.State.PopCallStackFrameWithStackPop();
             }
 
             return r;

+ 99 - 99
src/Lua/Runtime/LuaVirtualMachine.cs

@@ -16,7 +16,7 @@ public static partial class LuaVirtualMachine
     {
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static VirtualMachineExecutionContext Get(
-            LuaThread thread,
+            LuaState thread,
             in CallStackFrame frame,
             CancellationToken cancellationToken)
         {
@@ -30,12 +30,12 @@ public static partial class LuaVirtualMachine
         }
 
         void Init(
-            LuaThread thread,
+            LuaState thread,
             in CallStackFrame frame,
             CancellationToken cancellationToken)
         {
             Stack = thread.Stack;
-            Thread = thread;
+            State = thread;
             LuaClosure = (LuaClosure)frame.Function;
             FrameBase = frame.Base;
             VariableArgumentCount = frame.VariableArgumentCount;
@@ -49,11 +49,11 @@ public static partial class LuaVirtualMachine
             Task = default;
         }
 
-        public LuaState State => Thread.State;
+        public LuaGlobalState GlobalState => State.GlobalState;
 
         public LuaStack Stack = default!;
         public LuaClosure LuaClosure = default!;
-        public LuaThread Thread = default!;
+        public LuaState State = default!;
 
         public Prototype Prototype => LuaClosure.Proto;
 
@@ -66,7 +66,7 @@ public static partial class LuaVirtualMachine
         public ValueTask<int> Task;
         public int LastHookPc;
 
-        public bool IsTopLevel => BaseCallStackCount == Thread.CallStackFrameCount;
+        public bool IsTopLevel => BaseCallStackCount == State.CallStackFrameCount;
 
         public int BaseCallStackCount;
 
@@ -96,7 +96,7 @@ public static partial class LuaVirtualMachine
         {
             var result = Stack.GetBuffer().Slice(src, srcCount);
         Re:
-            var frames = Thread.GetCallStackFrames();
+            var frames = State.GetCallStackFrames();
             if (frames.Length == BaseCallStackCount)
             {
                 var returnBase = frames[^1].ReturnBase;
@@ -111,14 +111,14 @@ public static partial class LuaVirtualMachine
 
             ref readonly var frame = ref frames[^1];
             Pc = frame.CallerInstructionIndex;
-            Thread.LastPc = Pc;
+            State.LastPc = Pc;
             ref readonly var lastFrame = ref frames[^2];
             LuaClosure = Unsafe.As<LuaClosure>(lastFrame.Function);
             CurrentReturnFrameBase = frame.ReturnBase;
             var callInstruction = Prototype.Code[Pc];
             if (callInstruction.OpCode == OpCode.TailCall)
             {
-                Thread.PopCallStackFrame();
+                State.PopCallStackFrame();
                 goto Re;
             }
 
@@ -140,7 +140,7 @@ public static partial class LuaVirtualMachine
                     Pc++;
                 }
 
-                Thread.PopCallStackFrameWithStackPop();
+                State.PopCallStackFrameWithStackPop();
                 return true;
             }
 
@@ -164,7 +164,7 @@ public static partial class LuaVirtualMachine
                     break;
                 case OpCode.Self:
                     Stack.Get(target) = result.Length == 0 ? LuaValue.Nil : result[0];
-                    Thread.PopCallStackFrameWithStackPop(target + 2);
+                    State.PopCallStackFrameWithStackPop(target + 2);
                     return true;
                 case OpCode.SetTable or OpCode.SetTabUp:
                     target = frame.Base;
@@ -173,7 +173,7 @@ public static partial class LuaVirtualMachine
                 // Other opcodes has one result
                 default:
                     Stack.Get(target) = result.Length == 0 ? LuaValue.Nil : result[0];
-                    Thread.PopCallStackFrameWithStackPop(target + 1);
+                    State.PopCallStackFrameWithStackPop(target + 1);
                     return true;
             }
 
@@ -190,7 +190,7 @@ public static partial class LuaVirtualMachine
 
             Stack.PopUntil(target + Math.Min(targetCount, srcCount));
             Stack.NotifyTop(target + targetCount);
-            Thread.PopCallStackFrame();
+            State.PopCallStackFrame();
             return true;
         }
 
@@ -206,13 +206,13 @@ public static partial class LuaVirtualMachine
 
         public void PopOnTopCallStackFrames()
         {
-            var count = Thread.CallStackFrameCount;
+            var count = State.CallStackFrameCount;
             if (count == BaseCallStackCount)
             {
                 return;
             }
 
-            Thread.PopCallStackFrameUntil(BaseCallStackCount);
+            State.PopCallStackFrameUntil(BaseCallStackCount);
         }
 
         bool ExecutePostOperation(PostOperationType postOperation)
@@ -265,7 +265,7 @@ public static partial class LuaVirtualMachine
                     Task = default;
                     if (PostOperation is not (PostOperationType.TailCall or PostOperationType.DontPop))
                     {
-                        Thread.PopCallStackFrame();
+                        State.PopCallStackFrame();
                     }
 
                     if (!ExecutePostOperation(PostOperation))
@@ -278,16 +278,16 @@ public static partial class LuaVirtualMachine
                     ThrowIfCancellationRequested();
                 }
 
-                return Thread.Stack.Count - returnFrameBase;
+                return State.Stack.Count - returnFrameBase;
             }
             catch (Exception e)
             {
                 if (toCatchFlag)
                 {
-                    State.CloseUpValues(Thread, FrameBase);
+                    GlobalState.CloseUpValues(State, FrameBase);
                     if (e is not (LuaRuntimeException or LuaCanceledException))
                     {
-                        Exception newException = e is OperationCanceledException ? new LuaCanceledException(Thread, CancellationToken, e) : new LuaRuntimeException(Thread, e);
+                        Exception newException = e is OperationCanceledException ? new LuaCanceledException(State, CancellationToken, e) : new LuaRuntimeException(State, e);
                         PopOnTopCallStackFrames();
                         throw newException;
                     }
@@ -333,7 +333,7 @@ public static partial class LuaVirtualMachine
         DontPop
     }
 
-    internal static ValueTask<int> ExecuteClosureAsync(LuaThread thread, CancellationToken cancellationToken)
+    internal static ValueTask<int> ExecuteClosureAsync(LuaState thread, CancellationToken cancellationToken)
     {
         ref readonly var frame = ref thread.GetCurrentFrame();
 
@@ -357,8 +357,8 @@ public static partial class LuaVirtualMachine
             var stack = context.Stack;
             stack.EnsureCapacity(frameBase + context.Prototype.MaxStackSize);
             ref var constHead = ref MemoryMarshalEx.UnsafeElementAt(context.Prototype.Constants, 0);
-            ref var lineHookFlag = ref context.Thread.IsInHook ? ref DummyLineHookEnabled : ref context.Thread.IsLineHookEnabled;
-            ref var hookCount = ref context.Thread.IsInHook ? ref DummyHookCount : ref context.Thread.HookCount;
+            ref var lineHookFlag = ref context.State.IsInHook ? ref DummyLineHookEnabled : ref context.State.IsLineHookEnabled;
+            ref var hookCount = ref context.State.IsInHook ? ref DummyHookCount : ref context.State.HookCount;
             goto Loop;
         LineHook:
 
@@ -655,7 +655,7 @@ public static partial class LuaVirtualMachine
 
                         if (iA != 0)
                         {
-                            context.Thread.State.CloseUpValues(context.Thread, frameBase + iA - 1);
+                            context.State.GlobalState.CloseUpValues(context.State, frameBase + iA - 1);
                         }
 
                         context.ThrowIfCancellationRequested();
@@ -783,7 +783,7 @@ public static partial class LuaVirtualMachine
                         return true;
                     case OpCode.Return:
                         Markers.Return();
-                        context.State.CloseUpValues(context.Thread, frameBase);
+                        context.GlobalState.CloseUpValues(context.State, frameBase);
                         if (context.Pop(instruction, frameBase))
                         {
                             goto Restart;
@@ -867,7 +867,7 @@ public static partial class LuaVirtualMachine
                         Markers.Closure();
                         ra1 = iA + frameBase + 1;
                         stack.EnsureCapacity(ra1);
-                        stack.Get(ra1 - 1) = new LuaClosure(context.Thread, context.Prototype.ChildPrototypes[instruction.Bx]);
+                        stack.Get(ra1 - 1) = new LuaClosure(context.State, context.Prototype.ChildPrototypes[instruction.Bx]);
                         stack.NotifyTop(ra1);
                         continue;
                     case OpCode.VarArg:
@@ -912,10 +912,10 @@ public static partial class LuaVirtualMachine
         }
         catch (Exception e)
         {
-            context.State.CloseUpValues(context.Thread, context.FrameBase);
+            context.GlobalState.CloseUpValues(context.State, context.FrameBase);
             if (e is not (LuaRuntimeException or LuaCanceledException))
             {
-                Exception newException = e is OperationCanceledException ? new LuaCanceledException(context.Thread, context.CancellationToken, e) : new LuaRuntimeException(context.Thread, e);
+                Exception newException = e is OperationCanceledException ? new LuaCanceledException(context.State, context.CancellationToken, e) : new LuaRuntimeException(context.State, e);
                 context.PopOnTopCallStackFrames();
                 throw newException;
             }
@@ -1003,7 +1003,7 @@ public static partial class LuaVirtualMachine
         var stack = context.Stack;
         do
         {
-            var top = context.Thread.Stack.Count;
+            var top = context.State.Stack.Count;
             var n = 2;
             ref var lhs = ref stack.Get(top - 2);
             ref var rhs = ref stack.Get(top - 1);
@@ -1062,7 +1062,7 @@ public static partial class LuaVirtualMachine
         return 1;
     }
 
-    internal static async ValueTask<LuaValue> Concat(LuaThread thread, int total, CancellationToken ct)
+    internal static async ValueTask<LuaValue> Concat(LuaState thread, int total, CancellationToken ct)
     {
         static bool ToString(ref LuaValue v)
         {
@@ -1146,15 +1146,15 @@ public static partial class LuaVirtualMachine
     {
         context.ThrowIfCancellationRequested();
         var (name, description) = opCode.GetNameAndDescription();
-        if (vb.TryGetMetamethod(context.State, name, out var metamethod) ||
-            vc.TryGetMetamethod(context.State, name, out metamethod))
+        if (vb.TryGetMetamethod(context.GlobalState, name, out var metamethod) ||
+            vc.TryGetMetamethod(context.GlobalState, name, out metamethod))
         {
             var stack = context.Stack;
             var argCount = 2;
             var callable = metamethod;
             if (!metamethod.TryReadFunction(out var func))
             {
-                if (metamethod.TryGetMetamethod(context.State, Metamethods.Call, out metamethod) &&
+                if (metamethod.TryGetMetamethod(context.GlobalState, Metamethods.Call, out metamethod) &&
                     metamethod.TryReadFunction(out func))
                 {
                     stack.Push(callable);
@@ -1171,7 +1171,7 @@ public static partial class LuaVirtualMachine
             var varArgCount = func.GetVariableArgumentCount(argCount);
 
             var newFrame = func.CreateNewFrame(context, stack.Count - argCount + varArgCount, target, varArgCount);
-            var thread = context.Thread;
+            var thread = context.State;
             var access = thread.PushCallStackFrame(newFrame);
             try
             {
@@ -1212,7 +1212,7 @@ public static partial class LuaVirtualMachine
         var isMetamethod = false;
         if (!va.TryReadFunction(out var func))
         {
-            if (va.TryGetMetamethod(context.State, Metamethods.Call, out var metamethod) &&
+            if (va.TryGetMetamethod(context.GlobalState, Metamethods.Call, out var metamethod) &&
                 metamethod.TryReadFunction(out func))
             {
                 newBase -= 1;
@@ -1224,7 +1224,7 @@ public static partial class LuaVirtualMachine
             }
         }
 
-        var thread = context.Thread;
+        var thread = context.State;
         var (argumentCount, variableArgumentCount) = PrepareForFunctionCall(thread, func, instruction, newBase, isMetamethod);
         newBase += variableArgumentCount;
         thread.Stack.PopUntil(newBase + argumentCount);
@@ -1232,7 +1232,7 @@ public static partial class LuaVirtualMachine
         var newFrame = func.CreateNewFrame(context, newBase, RA, variableArgumentCount);
 
         var access = thread.PushCallStackFrame(newFrame);
-        if (thread.CallOrReturnHookMask.Value != 0 && !context.Thread.IsInHook)
+        if (thread.CallOrReturnHookMask.Value != 0 && !context.State.IsInHook)
         {
             context.PostOperation = PostOperationType.Call;
             context.Task = ExecuteCallHook(context, newFrame, argumentCount);
@@ -1264,7 +1264,7 @@ public static partial class LuaVirtualMachine
             var awaiter = task.GetAwaiter();
 
             awaiter.GetResult();
-            context.Thread.ThrowIfCancellationRequested(context.CancellationToken);
+            context.State.ThrowIfCancellationRequested(context.CancellationToken);
             var instruction = context.Instruction;
             var ic = instruction.C;
 
@@ -1278,12 +1278,12 @@ public static partial class LuaVirtualMachine
                 stack.NotifyTop(top);
             }
 
-            context.Thread.PopCallStackFrame();
+            context.State.PopCallStackFrame();
             return true;
         }
     }
 
-    internal static async ValueTask<int> Call(LuaThread thread, int funcIndex, int returnBase, CancellationToken cancellationToken)
+    internal static async ValueTask<int> Call(LuaState thread, int funcIndex, int returnBase, CancellationToken cancellationToken)
     {
         thread.ThrowIfCancellationRequested(cancellationToken);
         var stack = thread.Stack;
@@ -1291,7 +1291,7 @@ public static partial class LuaVirtualMachine
         var va = stack.Get(funcIndex);
         if (!va.TryReadFunction(out var func))
         {
-            if (va.TryGetMetamethod(thread.State, Metamethods.Call, out va) &&
+            if (va.TryGetMetamethod(thread.GlobalState, Metamethods.Call, out va) &&
                 va.TryReadFunction(out func))
             {
                 newBase--;
@@ -1361,8 +1361,8 @@ public static partial class LuaVirtualMachine
         var RA = instruction.A + context.FrameBase;
         var newBase = RA + 1;
         var isMetamethod = false;
-        var state = context.State;
-        var thread = context.Thread;
+        var state = context.GlobalState;
+        var thread = context.State;
 
         state.CloseUpValues(thread, context.FrameBase);
 
@@ -1387,14 +1387,14 @@ public static partial class LuaVirtualMachine
         var lastFrame = thread.GetCurrentFrame();
         thread.LastPc = context.Pc;
         thread.LastCallerFunction = lastFrame.Function;
-        context.Thread.PopCallStackFrame();
+        context.State.PopCallStackFrame();
         var newFrame = func.CreateNewTailCallFrame(context, newBase, lastFrame.ReturnBase, variableArgumentCount);
 
         newFrame.CallerInstructionIndex = lastFrame.CallerInstructionIndex;
         newFrame.Version = lastFrame.Version;
         var access = thread.PushCallStackFrame(newFrame);
 
-        if (thread.CallOrReturnHookMask.Value != 0 && !context.Thread.IsInHook)
+        if (thread.CallOrReturnHookMask.Value != 0 && !context.State.IsInHook)
         {
             context.PostOperation = PostOperationType.TailCall;
             context.Task = ExecuteCallHook(context, newFrame, argumentCount, true);
@@ -1443,7 +1443,7 @@ public static partial class LuaVirtualMachine
         var iteratorRaw = stack.Get(RA);
         if (!iteratorRaw.TryReadFunction(out var iterator))
         {
-            if (iteratorRaw.TryGetMetamethod(context.State, Metamethods.Call, out var metamethod) &&
+            if (iteratorRaw.TryGetMetamethod(context.GlobalState, Metamethods.Call, out var metamethod) &&
                 metamethod.TryReadFunction(out iterator))
             {
                 isMetamethod = true;
@@ -1481,8 +1481,8 @@ public static partial class LuaVirtualMachine
         stack.PopUntil(newBase + argumentCount);
 
         var newFrame = iterator.CreateNewFrame(context, newBase, RA + 3, variableArgumentCount);
-        var access = context.Thread.PushCallStackFrame(newFrame);
-        if (context.Thread.CallOrReturnHookMask.Value != 0 && !context.Thread.IsInHook)
+        var access = context.State.PushCallStackFrame(newFrame);
+        if (context.State.CallOrReturnHookMask.Value != 0 && !context.State.IsInHook)
         {
             context.PostOperation = PostOperationType.TForCall;
             context.Task = ExecuteCallHook(context, newFrame, stack.Count - newBase);
@@ -1508,7 +1508,7 @@ public static partial class LuaVirtualMachine
 
         task.GetAwaiter().GetResult();
         context.ThrowIfCancellationRequested();
-        context.Thread.PopCallStackFrame();
+        context.State.PopCallStackFrame();
         TForCallPostOperation(context);
         return true;
     }
@@ -1602,7 +1602,7 @@ public static partial class LuaVirtualMachine
                 return true;
             }
 
-            if (!table.TryGetMetamethod(context.State, Metamethods.Index, out var metatableValue))
+            if (!table.TryGetMetamethod(context.GlobalState, Metamethods.Index, out var metatableValue))
             {
                 if (i == 0)
                 {
@@ -1648,8 +1648,8 @@ public static partial class LuaVirtualMachine
         stack.Push(key);
         var newFrame = indexTable.CreateNewFrame(context, stack.Count - 2);
 
-        var access = context.Thread.PushCallStackFrame(newFrame);
-        if (context.Thread.CallOrReturnHookMask.Value != 0 && !context.Thread.IsInHook)
+        var access = context.State.PushCallStackFrame(newFrame);
+        if (context.State.CallOrReturnHookMask.Value != 0 && !context.State.IsInHook)
         {
             context.PostOperation = context.Instruction.OpCode == OpCode.GetTable ? PostOperationType.SetResult : PostOperationType.Self;
             context.Task = ExecuteCallHook(context, newFrame, 2);
@@ -1680,12 +1680,12 @@ public static partial class LuaVirtualMachine
         awaiter.GetResult();
         var results = stack.GetBuffer()[newFrame.ReturnBase..];
         result = results.Length == 0 ? default : results[0];
-        context.Thread.PopCallStackFrameWithStackPop();
+        context.State.PopCallStackFrameWithStackPop();
         return true;
     }
 
     [MethodImpl(MethodImplOptions.NoInlining)]
-    internal static ValueTask<LuaValue> ExecuteGetTableSlowPath(LuaThread thread, LuaValue table, LuaValue key, CancellationToken ct)
+    internal static ValueTask<LuaValue> ExecuteGetTableSlowPath(LuaState thread, LuaValue table, LuaValue key, CancellationToken ct)
     {
         var targetTable = table;
         const int MAX_LOOP = 100;
@@ -1710,7 +1710,7 @@ public static partial class LuaVirtualMachine
                 return default;
             }
 
-            if (!table.TryGetMetamethod(thread.State, Metamethods.Index, out var metatableValue))
+            if (!table.TryGetMetamethod(thread.GlobalState, Metamethods.Index, out var metatableValue))
             {
                 LuaRuntimeException.AttemptInvalidOperation(thread, "index", table);
             }
@@ -1727,7 +1727,7 @@ public static partial class LuaVirtualMachine
     }
 
     [MethodImpl(MethodImplOptions.NoInlining)]
-    static async ValueTask<LuaValue> CallGetTableFunc(LuaThread thread, LuaFunction indexTable, LuaValue table, LuaValue key, CancellationToken ct)
+    static async ValueTask<LuaValue> CallGetTableFunc(LuaState thread, LuaFunction indexTable, LuaValue table, LuaValue key, CancellationToken ct)
     {
         var stack = thread.Stack;
         var top = stack.Count;
@@ -1788,7 +1788,7 @@ public static partial class LuaVirtualMachine
                 goto Function;
             }
 
-            if (!table.TryGetMetamethod(context.State, Metamethods.NewIndex, out var metatableValue))
+            if (!table.TryGetMetamethod(context.GlobalState, Metamethods.NewIndex, out var metatableValue))
             {
                 if (i == 0)
                 {
@@ -1831,15 +1831,15 @@ public static partial class LuaVirtualMachine
     static bool CallSetTableFunc(LuaValue table, LuaFunction newIndexFunction, LuaValue key, LuaValue value, VirtualMachineExecutionContext context, out bool doRestart)
     {
         doRestart = false;
-        var thread = context.Thread;
+        var thread = context.State;
         var stack = thread.Stack;
         stack.Push(table);
         stack.Push(key);
         stack.Push(value);
         var newFrame = newIndexFunction.CreateNewFrame(context, stack.Count - 3);
 
-        var access = context.Thread.PushCallStackFrame(newFrame);
-        if (context.Thread.CallOrReturnHookMask.Value != 0 && !context.Thread.IsInHook)
+        var access = context.State.PushCallStackFrame(newFrame);
+        if (context.State.CallOrReturnHookMask.Value != 0 && !context.State.IsInHook)
         {
             context.PostOperation = PostOperationType.Nop;
             context.Task = ExecuteCallHook(context, newFrame, 3);
@@ -1867,7 +1867,7 @@ public static partial class LuaVirtualMachine
         return true;
     }
 
-    internal static ValueTask ExecuteSetTableSlowPath(LuaThread thread, LuaValue table, LuaValue key, LuaValue value, CancellationToken ct)
+    internal static ValueTask ExecuteSetTableSlowPath(LuaState thread, LuaValue table, LuaValue key, LuaValue value, CancellationToken ct)
     {
         var targetTable = table;
         const int MAX_LOOP = 100;
@@ -1901,7 +1901,7 @@ public static partial class LuaVirtualMachine
                 goto Function;
             }
 
-            if (!table.TryGetMetamethod(thread.State, Metamethods.NewIndex, out var metatableValue))
+            if (!table.TryGetMetamethod(thread.GlobalState, Metamethods.NewIndex, out var metatableValue))
             {
                 LuaRuntimeException.AttemptInvalidOperation(thread, "index", table);
             }
@@ -1919,7 +1919,7 @@ public static partial class LuaVirtualMachine
     }
 
     [MethodImpl(MethodImplOptions.NoInlining)]
-    static async ValueTask CallSetTableFunc(LuaThread thread, LuaFunction newIndexFunction, LuaValue table, LuaValue key, LuaValue value, CancellationToken ct)
+    static async ValueTask CallSetTableFunc(LuaState thread, LuaFunction newIndexFunction, LuaValue table, LuaValue key, LuaValue value, CancellationToken ct)
     {
         var stack = thread.Stack;
         var top = stack.Count;
@@ -1947,15 +1947,15 @@ public static partial class LuaVirtualMachine
     {
         var (name, description) = opCode.GetNameAndDescription();
         doRestart = false;
-        if (vb.TryGetMetamethod(context.State, name, out var metamethod) ||
-            vc.TryGetMetamethod(context.State, name, out metamethod))
+        if (vb.TryGetMetamethod(context.GlobalState, name, out var metamethod) ||
+            vc.TryGetMetamethod(context.GlobalState, name, out metamethod))
         {
             var stack = context.Stack;
             var newBase = stack.Count;
             var callable = metamethod;
             if (!metamethod.TryReadFunction(out var func))
             {
-                if (metamethod.TryGetMetamethod(context.State, Metamethods.Call, out metamethod) &&
+                if (metamethod.TryGetMetamethod(context.GlobalState, Metamethods.Call, out metamethod) &&
                     metamethod.TryReadFunction(out func))
                 {
                     stack.Push(callable);
@@ -1968,12 +1968,12 @@ public static partial class LuaVirtualMachine
 
             stack.Push(vb);
             stack.Push(vc);
-            var (argCount, variableArgumentCount) = PrepareForFunctionCall(context.Thread, func, newBase);
+            var (argCount, variableArgumentCount) = PrepareForFunctionCall(context.State, func, newBase);
             newBase += variableArgumentCount;
             var newFrame = func.CreateNewFrame(context, newBase, newBase, variableArgumentCount);
 
-            var access = context.Thread.PushCallStackFrame(newFrame);
-            if (context.Thread.CallOrReturnHookMask.Value != 0 && !context.Thread.IsInHook)
+            var access = context.State.PushCallStackFrame(newFrame);
+            if (context.State.CallOrReturnHookMask.Value != 0 && !context.State.IsInHook)
             {
                 context.PostOperation = PostOperationType.SetResult;
                 context.Task = ExecuteCallHook(context, newFrame, argCount);
@@ -2003,7 +2003,7 @@ public static partial class LuaVirtualMachine
                     ? stack.FastGet(newFrame.ReturnBase)
                     : default;
             stack.PopUntil(newBase - variableArgumentCount);
-            context.Thread.PopCallStackFrame();
+            context.State.PopCallStackFrame();
             return true;
         }
 
@@ -2012,19 +2012,19 @@ public static partial class LuaVirtualMachine
     }
 
     [MethodImpl(MethodImplOptions.NoInlining)]
-    internal static async ValueTask<LuaValue> ExecuteBinaryOperationMetaMethod(LuaThread thread, LuaValue vb, LuaValue vc, OpCode opCode, CancellationToken ct)
+    internal static async ValueTask<LuaValue> ExecuteBinaryOperationMetaMethod(LuaState thread, LuaValue vb, LuaValue vc, OpCode opCode, CancellationToken ct)
     {
         var (name, description) = opCode.GetNameAndDescription();
 
-        if (vb.TryGetMetamethod(thread.State, name, out var metamethod) ||
-            vc.TryGetMetamethod(thread.State, name, out metamethod))
+        if (vb.TryGetMetamethod(thread.GlobalState, name, out var metamethod) ||
+            vc.TryGetMetamethod(thread.GlobalState, name, out metamethod))
         {
             var stack = thread.Stack;
             var newBase = stack.Count;
             var callable = metamethod;
             if (!metamethod.TryReadFunction(out var func))
             {
-                if (metamethod.TryGetMetamethod(thread.State, Metamethods.Call, out metamethod) &&
+                if (metamethod.TryGetMetamethod(thread.GlobalState, Metamethods.Call, out metamethod) &&
                     metamethod.TryReadFunction(out func))
                 {
                     stack.Push(callable);
@@ -2074,13 +2074,13 @@ public static partial class LuaVirtualMachine
         var (name, description) = opCode.GetNameAndDescription();
         doRestart = false;
         var stack = context.Stack;
-        if (vb.TryGetMetamethod(context.State, name, out var metamethod))
+        if (vb.TryGetMetamethod(context.GlobalState, name, out var metamethod))
         {
             var newBase = stack.Count;
             var callable = metamethod;
             if (!metamethod.TryReadFunction(out var func))
             {
-                if (metamethod.TryGetMetamethod(context.State, Metamethods.Call, out metamethod) &&
+                if (metamethod.TryGetMetamethod(context.GlobalState, Metamethods.Call, out metamethod) &&
                     metamethod.TryReadFunction(out func))
                 {
                     stack.Push(callable);
@@ -2094,13 +2094,13 @@ public static partial class LuaVirtualMachine
 
             stack.Push(vb);
             stack.Push(vb);
-            var (argCount, variableArgumentCount) = PrepareForFunctionCall(context.Thread, func, newBase);
+            var (argCount, variableArgumentCount) = PrepareForFunctionCall(context.State, func, newBase);
             newBase += variableArgumentCount;
 
             var newFrame = func.CreateNewFrame(context, newBase, newBase, variableArgumentCount);
 
-            var access = context.Thread.PushCallStackFrame(newFrame);
-            if (context.Thread.CallOrReturnHookMask.Value != 0 && !context.Thread.IsInHook)
+            var access = context.State.PushCallStackFrame(newFrame);
+            if (context.State.CallOrReturnHookMask.Value != 0 && !context.State.IsInHook)
             {
                 context.PostOperation = PostOperationType.SetResult;
                 context.Task = ExecuteCallHook(context, newFrame, argCount);
@@ -2130,7 +2130,7 @@ public static partial class LuaVirtualMachine
                 : default;
             stack.Get(context.Instruction.A + context.FrameBase) = result;
             stack.PopUntil(newBase - variableArgumentCount);
-            context.Thread.PopCallStackFrame();
+            context.State.PopCallStackFrame();
             return true;
         }
 
@@ -2146,20 +2146,20 @@ public static partial class LuaVirtualMachine
     }
 
     [MethodImpl(MethodImplOptions.NoInlining)]
-    internal static async ValueTask<LuaValue> ExecuteUnaryOperationMetaMethod(LuaThread thread, LuaValue vb, OpCode opCode, CancellationToken cancellationToken)
+    internal static async ValueTask<LuaValue> ExecuteUnaryOperationMetaMethod(LuaState thread, LuaValue vb, OpCode opCode, CancellationToken cancellationToken)
     {
         thread.ThrowIfCancellationRequested(cancellationToken);
 
         var (name, description) = opCode.GetNameAndDescription();
 
-        if (vb.TryGetMetamethod(thread.State, name, out var metamethod))
+        if (vb.TryGetMetamethod(thread.GlobalState, name, out var metamethod))
         {
             var stack = thread.Stack;
             var newBase = stack.Count;
             var callable = metamethod;
             if (!metamethod.TryReadFunction(out var func))
             {
-                if (metamethod.TryGetMetamethod(thread.State, Metamethods.Call, out metamethod) &&
+                if (metamethod.TryGetMetamethod(thread.GlobalState, Metamethods.Call, out metamethod) &&
                     metamethod.TryReadFunction(out func))
                 {
                     stack.Push(callable);
@@ -2213,15 +2213,15 @@ public static partial class LuaVirtualMachine
         doRestart = false;
         var reverseLe = false;
     ReCheck:
-        if (vb.TryGetMetamethod(context.State, name, out var metamethod) ||
-            vc.TryGetMetamethod(context.State, name, out metamethod))
+        if (vb.TryGetMetamethod(context.GlobalState, name, out var metamethod) ||
+            vc.TryGetMetamethod(context.GlobalState, name, out metamethod))
         {
             var stack = context.Stack;
             var argCount = 2;
             var callable = metamethod;
             if (!metamethod.TryReadFunction(out var func))
             {
-                if (metamethod.TryGetMetamethod(context.State, Metamethods.Call, out metamethod) &&
+                if (metamethod.TryGetMetamethod(context.GlobalState, Metamethods.Call, out metamethod) &&
                     metamethod.TryReadFunction(out func))
                 {
                     stack.Push(callable);
@@ -2242,8 +2242,8 @@ public static partial class LuaVirtualMachine
                 newFrame.Flags |= CallStackFrameFlags.ReversedLe;
             }
 
-            var access = context.Thread.PushCallStackFrame(newFrame);
-            if (context.Thread.CallOrReturnHookMask.Value != 0 && !context.Thread.IsInHook)
+            var access = context.State.PushCallStackFrame(newFrame);
+            if (context.State.CallOrReturnHookMask.Value != 0 && !context.State.IsInHook)
             {
                 context.PostOperation = PostOperationType.Compare;
                 context.Task = ExecuteCallHook(context, newFrame, argCount);
@@ -2276,7 +2276,7 @@ public static partial class LuaVirtualMachine
             }
 
             stack.PopUntil(newFrame.ReturnBase + 1);
-            context.Thread.PopCallStackFrame();
+            context.State.PopCallStackFrame();
 
             return true;
         }
@@ -2310,22 +2310,22 @@ public static partial class LuaVirtualMachine
     }
 
     [MethodImpl(MethodImplOptions.NoInlining)]
-    internal static async ValueTask<bool> ExecuteCompareOperationMetaMethod(LuaThread thread, LuaValue vb, LuaValue vc, OpCode opCode, CancellationToken cancellationToken)
+    internal static async ValueTask<bool> ExecuteCompareOperationMetaMethod(LuaState thread, LuaValue vb, LuaValue vc, OpCode opCode, CancellationToken cancellationToken)
     {
         thread.ThrowIfCancellationRequested(cancellationToken);
 
         var (name, description) = opCode.GetNameAndDescription();
         var reverseLe = false;
     ReCheck:
-        if (vb.TryGetMetamethod(thread.State, name, out var metamethod) ||
-            vc.TryGetMetamethod(thread.State, name, out metamethod))
+        if (vb.TryGetMetamethod(thread.GlobalState, name, out var metamethod) ||
+            vc.TryGetMetamethod(thread.GlobalState, name, out metamethod))
         {
             var stack = thread.Stack;
             var newBase = stack.Count;
             var callable = metamethod;
             if (!metamethod.TryReadFunction(out var func))
             {
-                if (metamethod.TryGetMetamethod(thread.State, Metamethods.Call, out metamethod) &&
+                if (metamethod.TryGetMetamethod(thread.GlobalState, Metamethods.Call, out metamethod) &&
                     metamethod.TryReadFunction(out func))
                 {
                     stack.Push(callable);
@@ -2425,7 +2425,7 @@ public static partial class LuaVirtualMachine
     }
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    static (int ArgumentCount, int VariableArgumentCount) PrepareForFunctionCall(LuaThread thread, LuaFunction function,
+    static (int ArgumentCount, int VariableArgumentCount) PrepareForFunctionCall(LuaState thread, LuaFunction function,
         Instruction instruction, int newBase, bool isMetamethod)
     {
         var argumentCount = instruction.B - 1;
@@ -2461,7 +2461,7 @@ public static partial class LuaVirtualMachine
     }
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    static (int ArgumentCount, int VariableArgumentCount) PrepareForFunctionCall(LuaThread thread, LuaFunction function,
+    static (int ArgumentCount, int VariableArgumentCount) PrepareForFunctionCall(LuaState thread, LuaFunction function,
         int newBase)
     {
         var argumentCount = (int)(thread.Stack.Count - newBase);
@@ -2484,7 +2484,7 @@ public static partial class LuaVirtualMachine
     }
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    static (int ArgumentCount, int VariableArgumentCount) PrepareForFunctionTailCall(LuaThread thread, LuaFunction function,
+    static (int ArgumentCount, int VariableArgumentCount) PrepareForFunctionTailCall(LuaState thread, LuaFunction function,
         Instruction instruction, int newBase, bool isMetamethod)
     {
         var stack = thread.Stack;
@@ -2528,14 +2528,14 @@ public static partial class LuaVirtualMachine
         return PrepareVariableArgument(thread.Stack, newBase, argumentCount, variableArgumentCount);
     }
 
-    static LuaThread GetThreadWithCurrentPc(VirtualMachineExecutionContext context)
+    static LuaState GetThreadWithCurrentPc(VirtualMachineExecutionContext context)
     {
-        GetThreadWithCurrentPc(context.Thread, context.Pc);
-        return context.Thread;
+        GetThreadWithCurrentPc(context.State, context.Pc);
+        return context.State;
     }
 
 
-    static void GetThreadWithCurrentPc(LuaThread thread, int pc)
+    static void GetThreadWithCurrentPc(LuaState thread, int pc)
     {
         var frame = thread.GetCurrentFrame();
         thread.PushCallStackFrame(frame with { CallerInstructionIndex = pc, Flags = frame.Flags & (0 ^ CallStackFrameFlags.TailCall) });

+ 8 - 8
src/Lua/Runtime/Tracebacks.cs

@@ -3,9 +3,9 @@ using Lua.Internal;
 
 namespace Lua.Runtime;
 
-public class Traceback(LuaState state, ReadOnlySpan<CallStackFrame> stackFrames)
+public class Traceback(LuaGlobalState globalState, ReadOnlySpan<CallStackFrame> stackFrames)
 {
-    public LuaState State => state;
+    public LuaGlobalState GlobalState => globalState;
 
     public LuaFunction RootFunc => StackFrames[0].Function;
 
@@ -108,7 +108,7 @@ public class Traceback(LuaState state, ReadOnlySpan<CallStackFrame> stackFrames)
 
     public override string ToString()
     {
-        return CreateTracebackMessage(State, StackFrames, LuaValue.Nil);
+        return CreateTracebackMessage(GlobalState, StackFrames, LuaValue.Nil);
     }
 
     public string ToString(int skipFrames)
@@ -118,15 +118,15 @@ public class Traceback(LuaState state, ReadOnlySpan<CallStackFrame> stackFrames)
             return "stack traceback:\n";
         }
 
-        return CreateTracebackMessage(State, StackFrames, LuaValue.Nil, skipFrames);
+        return CreateTracebackMessage(GlobalState, StackFrames, LuaValue.Nil, skipFrames);
     }
 
-    public static string CreateTracebackMessage(LuaThread thread, LuaValue message, int stackFramesSkipCount = 0)
+    public static string CreateTracebackMessage(LuaState thread, LuaValue message, int stackFramesSkipCount = 0)
     {
-        return CreateTracebackMessage(thread.State, thread.GetCallStackFrames(), message, stackFramesSkipCount);
+        return CreateTracebackMessage(thread.GlobalState, thread.GetCallStackFrames(), message, stackFramesSkipCount);
     }
 
-    internal static string CreateTracebackMessage(LuaState state, ReadOnlySpan<CallStackFrame> stackFrames, LuaValue message, int skipCount = 0)
+    internal static string CreateTracebackMessage(LuaGlobalState globalState, ReadOnlySpan<CallStackFrame> stackFrames, LuaValue message, int skipCount = 0)
     {
         using var list = new PooledList<char>(64);
         if (message.Type is not LuaValueType.Nil)
@@ -200,7 +200,7 @@ public class Traceback(LuaState state, ReadOnlySpan<CallStackFrame> stackFrames)
                     goto Next;
                 }
 
-                foreach (var pair in state.Environment.Dictionary)
+                foreach (var pair in globalState.Environment.Dictionary)
                 {
                     if (pair.Key.TryReadString(out var name)
                         && pair.Value.TryReadFunction(out var result) &&

+ 3 - 3
src/Lua/Runtime/UpValue.cs

@@ -6,16 +6,16 @@ public sealed class UpValue
 {
     LuaValue value;
 
-    public LuaThread? Thread { get; }
+    public LuaState? Thread { get; }
     public bool IsClosed { get; private set; }
     public int RegisterIndex { get; private set; }
 
-    UpValue(LuaThread? thread)
+    UpValue(LuaState? thread)
     {
         Thread = thread;
     }
 
-    public static UpValue Open(LuaThread thread, int registerIndex)
+    public static UpValue Open(LuaState thread, int registerIndex)
     {
         return new(thread) { RegisterIndex = registerIndex };
     }

+ 31 - 31
src/Lua/Standard/BasicLibrary.cs

@@ -74,7 +74,7 @@ public sealed class BasicLibrary
                 message = context.GetArgument<string>(1);
             }
 
-            throw new LuaAssertionException(context.Thread, message);
+            throw new LuaAssertionException(context.State, message);
         }
 
         return new(context.Return(context.Arguments));
@@ -94,8 +94,8 @@ public sealed class BasicLibrary
     public async ValueTask<int> DoFile(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<string>(0);
-        context.Thread.Stack.PopUntil(context.ReturnFrameBase);
-        var closure = await context.State.LoadFileAsync(arg0, "bt", null, cancellationToken);
+        context.State.Stack.PopUntil(context.ReturnFrameBase);
+        var closure = await context.GlobalState.LoadFileAsync(arg0, "bt", null, cancellationToken);
         return await context.Access.RunAsync(closure, cancellationToken);
     }
 
@@ -108,14 +108,14 @@ public sealed class BasicLibrary
             ? context.GetArgument<int>(1)
             : 1;
 
-        throw new LuaRuntimeException(context.Thread, value, level);
+        throw new LuaRuntimeException(context.State, value, level);
     }
 
     public ValueTask<int> GetMetatable(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument(0);
 
-        if (context.State.TryGetMetatable(arg0, out var metatable))
+        if (context.GlobalState.TryGetMetatable(arg0, out var metatable))
         {
             if (metatable.TryGetValue(Metamethods.Metatable, out var metaMetatable))
             {
@@ -141,12 +141,12 @@ public sealed class BasicLibrary
         // If table has a metamethod __ipairs, calls it with table as argument and returns the first three results from the call.
         if (arg0.Metatable != null && arg0.Metatable.TryGetValue(Metamethods.IPairs, out var metamethod))
         {
-            var stack = context.Thread.Stack;
+            var stack = context.State.Stack;
             var top = stack.Count;
             stack.Push(metamethod);
             stack.Push(arg0);
 
-            await LuaVirtualMachine.Call(context.Access.Thread, top, context.ReturnFrameBase, cancellationToken);
+            await LuaVirtualMachine.Call(context.Access.State, top, context.ReturnFrameBase, cancellationToken);
             stack.SetTop(context.ReturnFrameBase + 3);
             return 3;
         }
@@ -167,7 +167,7 @@ public sealed class BasicLibrary
         // do not use LuaState.DoFileAsync as it uses the newExecutionContext
         try
         {
-            return context.Return(await context.State.LoadFileAsync(arg0, mode, arg2, cancellationToken));
+            return context.Return(await context.GlobalState.LoadFileAsync(arg0, mode, arg2, cancellationToken));
         }
         catch (Exception ex)
         {
@@ -197,7 +197,7 @@ public sealed class BasicLibrary
         {
             if (arg0.TryRead<string>(out var str))
             {
-                return new(context.Return(context.State.Load(str, name ?? str, arg3)));
+                return new(context.Return(context.GlobalState.Load(str, name ?? str, arg3)));
             }
             else if (arg0.TryRead<LuaFunction>(out var function))
             {
@@ -206,7 +206,7 @@ public sealed class BasicLibrary
             }
             else
             {
-                LuaRuntimeException.BadArgument(context.Thread, 1, ["string", "function,binary data"], arg0.TypeToString());
+                LuaRuntimeException.BadArgument(context.State, 1, ["string", "function,binary data"], arg0.TypeToString());
                 return default; // dummy
             }
         }
@@ -238,12 +238,12 @@ public sealed class BasicLibrary
         // If table has a metamethod __pairs, calls it with table as argument and returns the first three results from the call.
         if (arg0.Metatable != null && arg0.Metatable.TryGetValue(Metamethods.Pairs, out var metamethod))
         {
-            var stack = context.Thread.Stack;
+            var stack = context.State.Stack;
             var top = stack.Count;
             stack.Push(metamethod);
             stack.Push(arg0);
 
-            await LuaVirtualMachine.Call(context.Access.Thread, top, context.ReturnFrameBase, cancellationToken);
+            await LuaVirtualMachine.Call(context.Access.State, top, context.ReturnFrameBase, cancellationToken);
             stack.SetTop(context.ReturnFrameBase + 3);
             return 3;
         }
@@ -253,23 +253,23 @@ public sealed class BasicLibrary
 
     public async ValueTask<int> PCall(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
-        var frameCount = context.Thread.CallStackFrameCount;
+        var frameCount = context.State.CallStackFrameCount;
         try
         {
-            var count = await LuaVirtualMachine.Call(context.Access.Thread, context.FrameBase, context.ReturnFrameBase + 1, cancellationToken);
+            var count = await LuaVirtualMachine.Call(context.Access.State, context.FrameBase, context.ReturnFrameBase + 1, cancellationToken);
 
-            context.Thread.Stack.Get(context.ReturnFrameBase) = true;
+            context.State.Stack.Get(context.ReturnFrameBase) = true;
             return count + 1;
         }
         catch (Exception ex)
         {
-            context.Thread.PopCallStackFrameUntil(frameCount);
+            context.State.PopCallStackFrameUntil(frameCount);
             switch (ex)
             {
                 case LuaCanceledException:
                     throw;
                 case OperationCanceledException:
-                    throw new LuaCanceledException(context.Thread, cancellationToken, ex);
+                    throw new LuaCanceledException(context.State, cancellationToken, ex);
                 case LuaRuntimeException luaEx:
                     {
                         if (luaEx.InnerException == null && luaEx.ErrorObject.Type != LuaValueType.String)
@@ -290,12 +290,12 @@ public sealed class BasicLibrary
 
     public async ValueTask<int> Print(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
-        var stdout = context.State.StandardIO.Output;
+        var stdout = context.GlobalState.StandardIO.Output;
 
         for (var i = 0; i < context.ArgumentCount; i++)
         {
             await context.Arguments[i].CallToStringAsync(context, cancellationToken);
-            await stdout.WriteAsync(context.Thread.Stack.Pop().Read<string>(), cancellationToken);
+            await stdout.WriteAsync(context.State.Stack.Pop().Read<string>(), cancellationToken);
             if (i < context.ArgumentCount - 1)
             {
                 await stdout.WriteAsync("\t", cancellationToken);
@@ -336,7 +336,7 @@ public sealed class BasicLibrary
         }
         else
         {
-            LuaRuntimeException.BadArgument(context.Thread, 2, [LuaValueType.String, LuaValueType.Table], arg0.Type);
+            LuaRuntimeException.BadArgument(context.State, 2, [LuaValueType.String, LuaValueType.Table], arg0.Type);
             return default;
         }
     }
@@ -359,7 +359,7 @@ public sealed class BasicLibrary
         {
             if (Math.Abs(index) > context.ArgumentCount)
             {
-                throw new LuaRuntimeException(context.Thread, "bad argument #1 to 'select' (index out of range)");
+                throw new LuaRuntimeException(context.State, "bad argument #1 to 'select' (index out of range)");
             }
 
             var span = index >= 0
@@ -374,7 +374,7 @@ public sealed class BasicLibrary
         }
         else
         {
-            LuaRuntimeException.BadArgument(context.Thread, 1, LuaValueType.Number, arg0.Type);
+            LuaRuntimeException.BadArgument(context.State, 1, LuaValueType.Number, arg0.Type);
             return default;
         }
     }
@@ -386,12 +386,12 @@ public sealed class BasicLibrary
 
         if (arg1.Type is not (LuaValueType.Nil or LuaValueType.Table))
         {
-            LuaRuntimeException.BadArgument(context.Thread, 2, [LuaValueType.Nil, LuaValueType.Table], arg1.Type);
+            LuaRuntimeException.BadArgument(context.State, 2, [LuaValueType.Nil, LuaValueType.Table], arg1.Type);
         }
 
         if (arg0.Metatable != null && arg0.Metatable.TryGetValue(Metamethods.Metatable, out _))
         {
-            throw new LuaRuntimeException(context.Thread, "cannot change a protected metatable");
+            throw new LuaRuntimeException(context.State, "cannot change a protected metatable");
         }
         else if (arg1.Type is LuaValueType.Nil)
         {
@@ -415,7 +415,7 @@ public sealed class BasicLibrary
 
         if (toBase != null && (toBase < 2 || toBase > 36))
         {
-            throw new LuaRuntimeException(context.Thread, "bad argument #2 to 'tonumber' (base out of range)");
+            throw new LuaRuntimeException(context.State, "bad argument #2 to 'tonumber' (base out of range)");
         }
 
         double? value = null;
@@ -577,22 +577,22 @@ public sealed class BasicLibrary
 
     public async ValueTask<int> XPCall(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
-        var frameCount = context.Thread.CallStackFrameCount;
+        var frameCount = context.State.CallStackFrameCount;
         var arg0 = context.GetArgument(0);
         var arg1 = context.GetArgument<LuaFunction>(1);
 
         try
         {
-            var stack = context.Thread.Stack;
+            var stack = context.State.Stack;
             stack.Get(context.FrameBase + 1) = arg0;
-            var count = await LuaVirtualMachine.Call(context.Access.Thread, context.FrameBase + 1, context.ReturnFrameBase + 1, cancellationToken);
+            var count = await LuaVirtualMachine.Call(context.Access.State, context.FrameBase + 1, context.ReturnFrameBase + 1, cancellationToken);
 
-            context.Thread.Stack.Get(context.ReturnFrameBase) = true;
+            context.State.Stack.Get(context.ReturnFrameBase) = true;
             return count + 1;
         }
         catch (Exception ex)
         {
-            var thread = context.Thread;
+            var thread = context.State;
             thread.PopCallStackFrameUntil(frameCount);
             cancellationToken.ThrowIfCancellationRequested();
 
@@ -610,7 +610,7 @@ public sealed class BasicLibrary
 
             // invoke error handler
             var count = await access.RunAsync(arg1, 1, context.ReturnFrameBase + 1, cancellationToken);
-            context.Thread.Stack.Get(context.ReturnFrameBase) = false;
+            context.State.Stack.Get(context.ReturnFrameBase) = false;
             return count + 1;
         }
     }

+ 28 - 28
src/Lua/Standard/BitwiseLibrary.cs

@@ -33,8 +33,8 @@ public sealed class BitwiseLibrary
         var x = context.GetArgument<double>(0);
         var disp = context.GetArgument<double>(1);
 
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, x);
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 2, disp);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 1, x);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 2, disp);
 
         var v = Bit32Helper.ToInt32(x);
         var a = (int)disp;
@@ -60,14 +60,14 @@ public sealed class BitwiseLibrary
         }
 
         var arg0 = context.GetArgument<double>(0);
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, arg0);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 1, arg0);
 
         var value = Bit32Helper.ToUInt32(arg0);
 
         for (var i = 1; i < context.ArgumentCount; i++)
         {
             var arg = context.GetArgument<double>(i);
-            LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1 + i, arg);
+            LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 1 + i, arg);
 
             var v = Bit32Helper.ToUInt32(arg);
             value &= v;
@@ -80,7 +80,7 @@ public sealed class BitwiseLibrary
     public ValueTask<int> BNot(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, arg0);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 1, arg0);
 
         var value = Bit32Helper.ToUInt32(arg0);
         return new(context.Return(~value));
@@ -94,14 +94,14 @@ public sealed class BitwiseLibrary
         }
 
         var arg0 = context.GetArgument<double>(0);
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, arg0);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 1, arg0);
 
         var value = Bit32Helper.ToUInt32(arg0);
 
         for (var i = 1; i < context.ArgumentCount; i++)
         {
             var arg = context.GetArgument<double>(i);
-            LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1 + i, arg);
+            LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 1 + i, arg);
 
             var v = Bit32Helper.ToUInt32(arg);
             value |= v;
@@ -119,14 +119,14 @@ public sealed class BitwiseLibrary
         }
 
         var arg0 = context.GetArgument<double>(0);
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, arg0);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 1, arg0);
 
         var value = Bit32Helper.ToUInt32(arg0);
 
         for (var i = 1; i < context.ArgumentCount; i++)
         {
             var arg = context.GetArgument<double>(i);
-            LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1 + i, arg);
+            LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 1 + i, arg);
 
             var v = Bit32Helper.ToUInt32(arg);
             value &= v;
@@ -143,14 +143,14 @@ public sealed class BitwiseLibrary
         }
 
         var arg0 = context.GetArgument<double>(0);
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, arg0);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 1, arg0);
 
         var value = Bit32Helper.ToUInt32(arg0);
 
         for (var i = 1; i < context.ArgumentCount; i++)
         {
             var arg = context.GetArgument<double>(i);
-            LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1 + i, arg);
+            LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 1 + i, arg);
 
             var v = Bit32Helper.ToUInt32(arg);
             value ^= v;
@@ -167,15 +167,15 @@ public sealed class BitwiseLibrary
             ? context.GetArgument<double>(2)
             : 1;
 
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, arg0);
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 2, arg1);
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 3, arg2);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 1, arg0);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 2, arg1);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 3, arg2);
 
         var n = Bit32Helper.ToUInt32(arg0);
         var field = (int)arg1;
         var width = (int)arg2;
 
-        Bit32Helper.ValidateFieldAndWidth(context.Thread, "extract", 2, field, width);
+        Bit32Helper.ValidateFieldAndWidth(context.State, "extract", 2, field, width);
 
         if (field == 0 && width == 32)
         {
@@ -193,8 +193,8 @@ public sealed class BitwiseLibrary
         var x = context.GetArgument<double>(0);
         var disp = context.GetArgument<double>(1);
 
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, x);
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 2, disp);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 1, x);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 2, disp);
 
         var v = Bit32Helper.ToUInt32(x);
         var a = (int)disp % 32;
@@ -217,8 +217,8 @@ public sealed class BitwiseLibrary
         var x = context.GetArgument<double>(0);
         var disp = context.GetArgument<double>(1);
 
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, x);
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 2, disp);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 1, x);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 2, disp);
 
         var v = Bit32Helper.ToUInt32(x);
         var a = (int)disp;
@@ -248,17 +248,17 @@ public sealed class BitwiseLibrary
             ? context.GetArgument<double>(3)
             : 1;
 
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, arg0);
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 2, arg1);
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 3, arg2);
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 4, arg3);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 1, arg0);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 2, arg1);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 3, arg2);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 4, arg3);
 
         var n = Bit32Helper.ToUInt32(arg0);
         var v = Bit32Helper.ToUInt32(arg1);
         var field = (int)arg2;
         var width = (int)arg3;
 
-        Bit32Helper.ValidateFieldAndWidth(context.Thread, "replace", 2, field, width);
+        Bit32Helper.ValidateFieldAndWidth(context.State, "replace", 2, field, width);
         uint mask;
         if (width == 32)
         {
@@ -279,8 +279,8 @@ public sealed class BitwiseLibrary
         var x = context.GetArgument<double>(0);
         var disp = context.GetArgument<double>(1);
 
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, x);
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 2, disp);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 1, x);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 2, disp);
 
         var v = Bit32Helper.ToUInt32(x);
         var a = (int)disp % 32;
@@ -302,8 +302,8 @@ public sealed class BitwiseLibrary
         var x = context.GetArgument<double>(0);
         var disp = context.GetArgument<double>(1);
 
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, x);
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 2, disp);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 1, x);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 2, disp);
 
         var v = Bit32Helper.ToUInt32(x);
         var a = (int)disp;

+ 12 - 12
src/Lua/Standard/CoroutineLibrary.cs

@@ -25,23 +25,23 @@ public sealed class CoroutineLibrary
     public ValueTask<int> Create(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<LuaFunction>(0);
-        return new(context.Return(LuaCoroutine.Create(context.Thread, arg0, true)));
+        return new(context.Return(LuaCoroutine.Create(context.State, arg0, true)));
     }
 
     public ValueTask<int> Resume(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
-        var thread = context.GetArgument<LuaThread>(0);
+        var thread = context.GetArgument<LuaState>(0);
         return thread.ResumeAsync(context with { ArgumentCount = context.ArgumentCount - 1 }, cancellationToken);
     }
 
     public ValueTask<int> Running(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
-        return new(context.Return(context.Thread, context.Thread == context.State.MainThread));
+        return new(context.Return(context.State, context.State == context.GlobalState.MainThread));
     }
 
     public ValueTask<int> Status(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
-        var thread = context.GetArgument<LuaThread>(0);
+        var thread = context.GetArgument<LuaState>(0);
         return new(context.Return(thread.GetStatus() switch
         {
             LuaThreadStatus.Normal => "normal",
@@ -55,36 +55,36 @@ public sealed class CoroutineLibrary
     public ValueTask<int> Wrap(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<LuaFunction>(0);
-        var thread = LuaCoroutine.Create(context.Thread, arg0, false);
+        var thread = LuaCoroutine.Create(context.State, arg0, false);
         return new(context.Return(new CSharpClosure("wrap", [thread],
             static async (context, cancellationToken) =>
             {
-                var thread = context.GetCsClosure()!.UpValues[0].Read<LuaThread>();
+                var thread = context.GetCsClosure()!.UpValues[0].Read<LuaState>();
                 if (thread is not LuaCoroutine coroutine)
                 {
                     return await thread.ResumeAsync(context, cancellationToken);
                 }
 
-                var stack = context.Thread.Stack;
+                var stack = context.State.Stack;
                 var frameBase = stack.Count;
-                context.Thread.PushCallStackFrame(new() { Base = frameBase, ReturnBase = context.ReturnFrameBase, VariableArgumentCount = 0, Function = coroutine.Function });
+                context.State.PushCallStackFrame(new() { Base = frameBase, ReturnBase = context.ReturnFrameBase, VariableArgumentCount = 0, Function = coroutine.Function });
                 try
                 {
                     await thread.ResumeAsync(context, cancellationToken);
-                    var result = context.GetReturnBuffer(context.Thread.Stack.Count - context.ReturnFrameBase);
+                    var result = context.GetReturnBuffer(context.State.Stack.Count - context.ReturnFrameBase);
                     result[1..].CopyTo(result);
-                    context.Thread.Stack.Pop();
+                    context.State.Stack.Pop();
                     return result.Length - 1;
                 }
                 finally
                 {
-                    context.Thread.PopCallStackFrame();
+                    context.State.PopCallStackFrame();
                 }
             })));
     }
 
     public ValueTask<int> Yield(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
-        return context.Thread.YieldAsync(context, cancellationToken);
+        return context.State.YieldAsync(context, cancellationToken);
     }
 }

+ 17 - 17
src/Lua/Standard/DebugLibrary.cs

@@ -35,26 +35,26 @@ public class DebugLibrary
     public readonly LibraryFunction[] Functions;
 
 
-    static LuaThread GetLuaThread(in LuaFunctionExecutionContext context, out int argOffset)
+    static LuaState GetLuaThread(in LuaFunctionExecutionContext context, out int argOffset)
     {
         if (context.ArgumentCount < 1)
         {
             argOffset = 0;
-            return context.Thread;
+            return context.State;
         }
 
-        if (context.GetArgument(0).TryRead<LuaThread>(out var thread))
+        if (context.GetArgument(0).TryRead<LuaState>(out var thread))
         {
             argOffset = 1;
             return thread;
         }
 
         argOffset = 0;
-        return context.Thread;
+        return context.State;
     }
 
 
-    static ref LuaValue FindLocal(LuaThread thread, int level, int index, out string? name)
+    static ref LuaValue FindLocal(LuaState thread, int level, int index, out string? name)
     {
         if (index == 0)
         {
@@ -270,7 +270,7 @@ public class DebugLibrary
     {
         var arg0 = context.GetArgument(0);
 
-        if (context.State.TryGetMetatable(arg0, out var table))
+        if (context.GlobalState.TryGetMetatable(arg0, out var table))
         {
             return new(context.Return(table));
         }
@@ -287,10 +287,10 @@ public class DebugLibrary
 
         if (arg1.Type is not (LuaValueType.Nil or LuaValueType.Table))
         {
-            LuaRuntimeException.BadArgument(context.Thread, 2, [LuaValueType.Nil, LuaValueType.Table], arg1.Type);
+            LuaRuntimeException.BadArgument(context.State, 2, [LuaValueType.Nil, LuaValueType.Table], arg1.Type);
         }
 
-        context.State.SetMetatable(arg0, arg1.UnsafeRead<LuaTable>());
+        context.GlobalState.SetMetatable(arg0, arg1.UnsafeRead<LuaTable>());
 
         return new(context.Return(arg0));
     }
@@ -364,12 +364,12 @@ public class DebugLibrary
 
         var skipCount = Math.Min(Math.Max(level - 1, 0), callStack.Length - 1);
         var frames = callStack[..^skipCount];
-        return new(context.Return(Runtime.Traceback.CreateTracebackMessage(context.State, frames, message, level == 1 ? 1 : 0)));
+        return new(context.Return(Runtime.Traceback.CreateTracebackMessage(context.GlobalState, frames, message, level == 1 ? 1 : 0)));
     }
 
     public ValueTask<int> GetRegistry(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
-        return new(context.Return(context.State.Registry));
+        return new(context.Return(context.GlobalState.Registry));
     }
 
     public ValueTask<int> UpValueId(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
@@ -431,15 +431,15 @@ public class DebugLibrary
             return 0;
         }
 
-        if (thread.IsReturnHookEnabled && context.Thread == thread)
+        if (thread.IsReturnHookEnabled && context.State == thread)
         {
             var stack = thread.Stack;
             var top = stack.Count;
             stack.Push("return");
             stack.Push(LuaValue.Nil);
-            context.Thread.IsInHook = true;
-            var frame = context.Thread.CurrentAccess.CreateCallStackFrame(hook, 2, top, 0);
-            var access = context.Thread.PushCallStackFrame(frame);
+            context.State.IsInHook = true;
+            var frame = context.State.CurrentAccess.CreateCallStackFrame(hook, 2, top, 0);
+            var access = context.State.PushCallStackFrame(frame);
             LuaFunctionExecutionContext funcContext = new() { Access = access, ArgumentCount = stack.Count - frame.Base, ReturnFrameBase = frame.ReturnBase };
             try
             {
@@ -447,8 +447,8 @@ public class DebugLibrary
             }
             finally
             {
-                context.Thread.IsInHook = false;
-                context.Thread.PopCallStackFrameWithStackPop();
+                context.State.IsInHook = false;
+                context.State.PopCallStackFrameWithStackPop();
             }
         }
 
@@ -510,7 +510,7 @@ public class DebugLibrary
             context.ThrowBadArgument(argOffset, "function or level expected");
         }
 
-        using var debug = LuaDebug.Create(context.State, previousFrame, currentFrame, functionToInspect, pc, what, out var isValid);
+        using var debug = LuaDebug.Create(context.GlobalState, previousFrame, currentFrame, functionToInspect, pc, what, out var isValid);
         if (!isValid)
         {
             context.ThrowBadArgument(argOffset + 1, "invalid option");

+ 3 - 3
src/Lua/Standard/FileHandle.cs

@@ -170,7 +170,7 @@ public class FileHandle : ILuaUserData
             var upValues = context.GetCsClosure()!.UpValues.AsMemory();
             var file = upValues.Span[0].Read<FileHandle>();
             context.Return();
-            var resultCount = await IOHelper.ReadAsync(context.Thread, file, "file.lines", 0, upValues[1..], true, cancellationToken);
+            var resultCount = await IOHelper.ReadAsync(context.State, file, "file.lines", 0, upValues[1..], true, cancellationToken);
             return resultCount;
         })));
     });
@@ -180,7 +180,7 @@ public class FileHandle : ILuaUserData
         var file = context.GetArgument<FileHandle>(0);
         var args = context.Arguments[1..].ToArray();
         context.Return();
-        var resultCount = await IOHelper.ReadAsync(context.Thread, file, "file.read", 1, args, false, cancellationToken);
+        var resultCount = await IOHelper.ReadAsync(context.State, file, "file.read", 1, args, false, cancellationToken);
         return resultCount;
     });
 
@@ -196,7 +196,7 @@ public class FileHandle : ILuaUserData
 
         if (whence is not ("set" or "cur" or "end"))
         {
-            throw new LuaRuntimeException(context.Thread, $"bad argument #2 to 'file.seek' (invalid option '{whence}')");
+            throw new LuaRuntimeException(context.State, $"bad argument #2 to 'file.seek' (invalid option '{whence}')");
         }
 
         try

+ 18 - 18
src/Lua/Standard/IOLibrary.cs

@@ -32,7 +32,7 @@ public sealed class IOLibrary
     {
         var file = context.HasArgument(0)
             ? context.GetArgument<FileHandle>(0)
-            : context.State.Registry["_IO_output"].Read<FileHandle>();
+            : context.GlobalState.Registry["_IO_output"].Read<FileHandle>();
 
         try
         {
@@ -47,7 +47,7 @@ public sealed class IOLibrary
 
     public async ValueTask<int> Flush(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
-        var file = context.State.Registry["_IO_output"].Read<FileHandle>();
+        var file = context.GlobalState.Registry["_IO_output"].Read<FileHandle>();
 
         try
         {
@@ -62,7 +62,7 @@ public sealed class IOLibrary
 
     public async ValueTask<int> Input(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
-        var registry = context.State.Registry;
+        var registry = context.GlobalState.Registry;
 
         if (context.ArgumentCount == 0 || context.Arguments[0].Type is LuaValueType.Nil)
         {
@@ -77,7 +77,7 @@ public sealed class IOLibrary
         }
         else
         {
-            var stream = await context.State.FileSystem.Open(arg.ToString(), LuaFileOpenMode.Read, cancellationToken);
+            var stream = await context.GlobalState.FileSystem.Open(arg.ToString(), LuaFileOpenMode.Read, cancellationToken);
             FileHandle handle = new(stream);
             registry["_IO_input"] = new(handle);
             return context.Return(new LuaValue(handle));
@@ -88,13 +88,13 @@ public sealed class IOLibrary
     {
         if (context.ArgumentCount == 0)
         {
-            var file = context.State.Registry["_IO_input"].Read<FileHandle>();
+            var file = context.GlobalState.Registry["_IO_input"].Read<FileHandle>();
             return context.Return(new CSharpClosure("iterator", [new(file)], static async (context, cancellationToken) =>
             {
                 var file = context.GetCsClosure()!.UpValues[0].Read<FileHandle>();
                 context.Return();
-                var resultCount = await IOHelper.ReadAsync(context.Thread, file, "io.lines", 0, Memory<LuaValue>.Empty, true, cancellationToken);
-                if (resultCount > 0 && context.Thread.Stack.Get(context.ReturnFrameBase).Type is LuaValueType.Nil)
+                var resultCount = await IOHelper.ReadAsync(context.State, file, "io.lines", 0, Memory<LuaValue>.Empty, true, cancellationToken);
+                if (resultCount > 0 && context.State.Stack.Get(context.ReturnFrameBase).Type is LuaValueType.Nil)
                 {
                     await file.Close(cancellationToken);
                 }
@@ -105,10 +105,10 @@ public sealed class IOLibrary
         else
         {
             var fileName = context.GetArgument<string>(0);
-            var stack = context.Thread.Stack;
+            var stack = context.State.Stack;
             context.Return();
 
-            await IOHelper.Open(context.Thread, fileName, "r", true, cancellationToken);
+            await IOHelper.Open(context.State, fileName, "r", true, cancellationToken);
 
             var file = stack.Get(context.ReturnFrameBase).Read<FileHandle>();
             var upValues = new LuaValue[context.Arguments.Length];
@@ -120,9 +120,9 @@ public sealed class IOLibrary
                 var upValues = context.GetCsClosure()!.UpValues;
                 var file = upValues[0].Read<FileHandle>();
                 var formats = upValues.AsMemory(1);
-                var stack = context.Thread.Stack;
+                var stack = context.State.Stack;
                 context.Return();
-                var resultCount = await IOHelper.ReadAsync(context.Thread, file, "io.lines", 0, formats, true, cancellationToken);
+                var resultCount = await IOHelper.ReadAsync(context.State, file, "io.lines", 0, formats, true, cancellationToken);
                 if (resultCount > 0 && stack.Get(context.ReturnFrameBase).Type is LuaValueType.Nil)
                 {
                     await file.Close(cancellationToken);
@@ -142,7 +142,7 @@ public sealed class IOLibrary
         context.Return();
         try
         {
-            var resultCount = await IOHelper.Open(context.Thread, fileName, mode, true, cancellationToken);
+            var resultCount = await IOHelper.Open(context.State, fileName, mode, true, cancellationToken);
             return resultCount;
         }
         catch (IOException ex)
@@ -153,7 +153,7 @@ public sealed class IOLibrary
 
     public async ValueTask<int> Output(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
-        var io = context.State.Registry;
+        var io = context.GlobalState.Registry;
 
         if (context.ArgumentCount == 0 || context.Arguments[0].Type is LuaValueType.Nil)
         {
@@ -168,7 +168,7 @@ public sealed class IOLibrary
         }
         else
         {
-            var stream = await context.State.FileSystem.Open(arg.ToString(), LuaFileOpenMode.WriteUpdate, cancellationToken);
+            var stream = await context.GlobalState.FileSystem.Open(arg.ToString(), LuaFileOpenMode.WriteUpdate, cancellationToken);
             FileHandle handle = new(stream);
             io["_IO_output"] = new(handle);
             return context.Return(new LuaValue(handle));
@@ -177,11 +177,11 @@ public sealed class IOLibrary
 
     public async ValueTask<int> Read(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
-        var file = context.State.Registry["_IO_input"].Read<FileHandle>();
+        var file = context.GlobalState.Registry["_IO_input"].Read<FileHandle>();
         var args = context.Arguments.ToArray();
         context.Return();
 
-        var resultCount = await IOHelper.ReadAsync(context.Thread, file, "io.read", 0, args, false, cancellationToken);
+        var resultCount = await IOHelper.ReadAsync(context.State, file, "io.read", 0, args, false, cancellationToken);
         return resultCount;
     }
 
@@ -201,13 +201,13 @@ public sealed class IOLibrary
 
     public async ValueTask<int> Write(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
-        var file = context.State.Registry["_IO_output"].Read<FileHandle>();
+        var file = context.GlobalState.Registry["_IO_output"].Read<FileHandle>();
         var resultCount = await IOHelper.WriteAsync(file, "io.write", context, cancellationToken);
         return resultCount;
     }
 
     public async ValueTask<int> TmpFile(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
-        return context.Return(LuaValue.FromUserData(new FileHandle(await context.State.FileSystem.OpenTempFileStream(cancellationToken))));
+        return context.Return(LuaValue.FromUserData(new FileHandle(await context.GlobalState.FileSystem.OpenTempFileStream(cancellationToken))));
     }
 }

+ 1 - 1
src/Lua/Standard/Internal/Bit32Helper.cs

@@ -18,7 +18,7 @@ static class Bit32Helper
         return (int)(long)Math.IEEERemainder(d, Bit32);
     }
 
-    public static void ValidateFieldAndWidth(LuaThread thread, string functionName, int argumentId, int field, int width)
+    public static void ValidateFieldAndWidth(LuaState thread, string functionName, int argumentId, int field, int width)
     {
         if (field > 31 || field + width > 32)
             throw new LuaRuntimeException(thread, "trying to access non-existent bits");

+ 3 - 3
src/Lua/Standard/Internal/DateTimeHelper.cs

@@ -30,9 +30,9 @@ static class DateTimeHelper
         return DateTime.UnixEpoch + ts;
     }
 
-    public static DateTime ParseTimeTable(LuaThread thread, LuaTable table)
+    public static DateTime ParseTimeTable(LuaState thread, LuaTable table)
     {
-        static int GetTimeField(LuaThread thread, LuaTable table, string key, bool required = true, int defaultValue = 0)
+        static int GetTimeField(LuaState thread, LuaTable table, string key, bool required = true, int defaultValue = 0)
         {
             if (!table.TryGetValue(key, out var value))
             {
@@ -64,7 +64,7 @@ static class DateTimeHelper
         return new(year, month, day, hour, min, sec);
     }
 
-    public static string StrFTime(LuaThread thread, ReadOnlySpan<char> format, DateTime d)
+    public static string StrFTime(LuaState thread, ReadOnlySpan<char> format, DateTime d)
     {
         // reference: http://www.cplusplus.com/reference/ctime/strftime/
 

+ 8 - 8
src/Lua/Standard/Internal/IOHelper.cs

@@ -7,7 +7,7 @@ namespace Lua.Standard.Internal;
 
 static class IOHelper
 {
-    public static async ValueTask<int> Open(LuaThread thread, string fileName, string mode, bool throwError, CancellationToken cancellationToken)
+    public static async ValueTask<int> Open(LuaState thread, string fileName, string mode, bool throwError, CancellationToken cancellationToken)
     {
         var fileMode = LuaFileOpenModeExtensions.ParseModeFromString(mode);
         if (!fileMode.IsValid())
@@ -17,7 +17,7 @@ static class IOHelper
 
         try
         {
-            var stream = await thread.State.FileSystem.Open(fileName, fileMode, cancellationToken);
+            var stream = await thread.GlobalState.FileSystem.Open(fileName, fileMode, cancellationToken);
 
             thread.Stack.Push(new(new FileHandle(stream)));
             return 1;
@@ -58,28 +58,28 @@ static class IOHelper
                 }
                 else
                 {
-                    LuaRuntimeException.BadArgument(context.Thread, i + 1, name);
+                    LuaRuntimeException.BadArgument(context.State, i + 1, name);
                 }
             }
         }
         catch (IOException ex)
         {
-            context.Thread.Stack.PopUntil(context.ReturnFrameBase);
-            var stack = context.Thread.Stack;
+            context.State.Stack.PopUntil(context.ReturnFrameBase);
+            var stack = context.State.Stack;
             stack.Push(LuaValue.Nil);
             stack.Push(ex.Message);
             stack.Push(ex.HResult);
             return 3;
         }
 
-        context.Thread.Stack.PopUntil(context.ReturnFrameBase);
-        context.Thread.Stack.Push(new(file));
+        context.State.Stack.PopUntil(context.ReturnFrameBase);
+        context.State.Stack.Push(new(file));
         return 1;
     }
 
     static readonly LuaValue[] defaultReadFormat = ["*l"];
 
-    public static async ValueTask<int> ReadAsync(LuaThread thread, FileHandle file, string name, int startArgumentIndex, ReadOnlyMemory<LuaValue> formats, bool throwError, CancellationToken cancellationToken)
+    public static async ValueTask<int> ReadAsync(LuaState thread, FileHandle file, string name, int startArgumentIndex, ReadOnlyMemory<LuaValue> formats, bool throwError, CancellationToken cancellationToken)
     {
         if (formats.Length == 0)
         {

+ 9 - 9
src/Lua/Standard/Internal/MatchState.cs

@@ -2,7 +2,7 @@ using System.Buffers;
 
 namespace Lua.Standard.Internal;
 
-class MatchState(LuaThread thread, string source, string pattern)
+class MatchState(LuaState thread, string source, string pattern)
 {
     internal const int LuaMaxCaptures = 32;
     const int CapUnfinished = -1;
@@ -19,7 +19,7 @@ class MatchState(LuaThread thread, string source, string pattern)
         public bool IsPosition => Len == CapPosition;
     }
 
-    public readonly LuaThread Thread = thread;
+    public readonly LuaState State = thread;
     public readonly string Source = source;
     public readonly string Pattern = pattern;
     public int Level = 0;
@@ -39,7 +39,7 @@ class MatchState(LuaThread thread, string source, string pattern)
     {
         if (Level >= LuaMaxCaptures)
         {
-            throw new LuaRuntimeException(Thread, "too many captures");
+            throw new LuaRuntimeException(State, "too many captures");
         }
 
         Captures[Level].Init = sIdx;
@@ -71,7 +71,7 @@ class MatchState(LuaThread thread, string source, string pattern)
     {
         if (MatchDepth-- == 0)
         {
-            throw new LuaRuntimeException(Thread, "pattern too complex");
+            throw new LuaRuntimeException(State, "pattern too complex");
         }
 
         var endIdx = Pattern.Length;
@@ -331,7 +331,7 @@ class MatchState(LuaThread thread, string source, string pattern)
             }
         }
 
-        throw new LuaRuntimeException(Thread, "invalid pattern capture");
+        throw new LuaRuntimeException(State, "invalid pattern capture");
     }
 
     int MatchCapture(int sIdx, int l)
@@ -354,7 +354,7 @@ class MatchState(LuaThread thread, string source, string pattern)
     {
         if (l < 0 || l >= Level || Captures[l].Len == CapUnfinished)
         {
-            throw new LuaRuntimeException(Thread, $"invalid capture index %{l + 1}");
+            throw new LuaRuntimeException(State, $"invalid capture index %{l + 1}");
         }
 
         return l;
@@ -364,7 +364,7 @@ class MatchState(LuaThread thread, string source, string pattern)
     {
         if (pIdx + 1 >= Pattern.Length)
         {
-            throw new LuaRuntimeException(Thread, "malformed pattern (missing arguments to '%b')");
+            throw new LuaRuntimeException(State, "malformed pattern (missing arguments to '%b')");
         }
 
         if (sIdx >= Source.Length || Source[sIdx] != Pattern[pIdx])
@@ -404,7 +404,7 @@ class MatchState(LuaThread thread, string source, string pattern)
             case LEsc:
                 if (pIdx >= pattern.Length)
                 {
-                    throw new LuaRuntimeException(Thread, "malformed pattern (ends with %)");
+                    throw new LuaRuntimeException(State, "malformed pattern (ends with %)");
                 }
 
                 return pIdx + 1;
@@ -425,7 +425,7 @@ class MatchState(LuaThread thread, string source, string pattern)
 
                     if (pIdx >= pattern.Length)
                     {
-                        throw new LuaRuntimeException(Thread, "malformed pattern (missing ']')");
+                        throw new LuaRuntimeException(State, "malformed pattern (missing ']')");
                     }
                 } while (pIdx < pattern.Length && pattern[pIdx] != ']');
 

+ 2 - 2
src/Lua/Standard/MathematicsLibrary.cs

@@ -206,7 +206,7 @@ public sealed class MathematicsLibrary
 
     public ValueTask<int> Random(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
-        var rand = context.State.Environment[RandomInstanceKey].Read<RandomUserData>().Random;
+        var rand = context.GlobalState.Environment[RandomInstanceKey].Read<RandomUserData>().Random;
 
         if (context.ArgumentCount == 0)
         {
@@ -228,7 +228,7 @@ public sealed class MathematicsLibrary
     public ValueTask<int> RandomSeed(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
-        context.State.Environment[RandomInstanceKey] = new(new RandomUserData(new((int)BitConverter.DoubleToInt64Bits(arg0))));
+        context.GlobalState.Environment[RandomInstanceKey] = new(new RandomUserData(new((int)BitConverter.DoubleToInt64Bits(arg0))));
         return new(context.Return());
     }
 

+ 15 - 15
src/Lua/Standard/ModuleLibrary.cs

@@ -20,18 +20,18 @@ public sealed class ModuleLibrary
     public async ValueTask<int> Require(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<string>(0);
-        var loaded = context.State.LoadedModules;
+        var loaded = context.GlobalState.LoadedModules;
 
         if (!loaded.TryGetValue(arg0, out var loadedTable))
         {
             LuaFunction loader;
-            var moduleLoader = context.State.ModuleLoader;
+            var moduleLoader = context.GlobalState.ModuleLoader;
             if (moduleLoader != null && moduleLoader.Exists(arg0))
             {
                 var module = await moduleLoader.LoadAsync(arg0, cancellationToken);
                 loader = module.Type == LuaModuleType.Bytes
-                    ? context.State.Load(module.ReadBytes(), module.Name)
-                    : context.State.Load(module.ReadText(), module.Name);
+                    ? context.GlobalState.Load(module.ReadBytes(), module.Name)
+                    : context.GlobalState.Load(module.ReadText(), module.Name);
             }
             else
             {
@@ -39,7 +39,7 @@ public sealed class ModuleLibrary
             }
 
             await context.Access.RunAsync(loader, 0, context.ReturnFrameBase, cancellationToken);
-            loadedTable = context.Thread.Stack.Get(context.ReturnFrameBase);
+            loadedTable = context.State.Stack.Get(context.ReturnFrameBase);
             loaded[arg0] = loadedTable;
         }
 
@@ -48,8 +48,8 @@ public sealed class ModuleLibrary
 
     internal static async ValueTask<string?> FindFile(LuaThreadAccess access, string name, string pName, string dirSeparator)
     {
-        var thread = access.Thread;
-        var state = thread.State;
+        var thread = access.State;
+        var state = thread.GlobalState;
         var package = state.Environment["package"];
         var p = await access.GetTable(package, pName);
         if (!p.TryReadString(out var path))
@@ -66,11 +66,11 @@ public sealed class ModuleLibrary
         var path = context.GetArgument<string>(1);
         var separator = context.GetArgument<string>(2);
         var dirSeparator = context.GetArgument<string>(3);
-        var fileName = SearchPath(context.State, name, path, separator, dirSeparator);
+        var fileName = SearchPath(context.GlobalState, name, path, separator, dirSeparator);
         return new(context.Return(fileName ?? LuaValue.Nil));
     }
 
-    internal static string? SearchPath(LuaState state, string name, string path, string separator, string dirSeparator)
+    internal static string? SearchPath(LuaGlobalState globalState, string name, string path, string separator, string dirSeparator)
     {
         if (separator != "")
         {
@@ -88,7 +88,7 @@ public sealed class ModuleLibrary
         {
             path = pathSpan[..nextIndex].ToString();
             var fileName = path.Replace("?", name);
-            if (state.FileSystem.IsReadable(fileName))
+            if (globalState.FileSystem.IsReadable(fileName))
             {
                 return fileName;
             }
@@ -111,7 +111,7 @@ public sealed class ModuleLibrary
 
     internal static async ValueTask<LuaFunction> FindLoader(LuaThreadAccess access, string name, CancellationToken cancellationToken)
     {
-        var state = access.State;
+        var state = access.GlobalState;
         var package = state.Environment["package"].Read<LuaTable>();
         var searchers = package["searchers"].Read<LuaTable>();
         for (var i = 0; i < searchers.GetArraySpan().Length; i++)
@@ -140,13 +140,13 @@ public sealed class ModuleLibrary
             access.Stack.SetTop(top);
         }
 
-        throw new LuaRuntimeException(access.Thread, $"Module '{name}' not found");
+        throw new LuaRuntimeException(access.State, $"Module '{name}' not found");
     }
 
     public ValueTask<int> SearcherPreload(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
         var name = context.GetArgument<string>(0);
-        var preload = context.State.PreloadModules[name];
+        var preload = context.GlobalState.PreloadModules[name];
         if (preload == LuaValue.Nil)
         {
             return new(context.Return());
@@ -158,12 +158,12 @@ public sealed class ModuleLibrary
     public async ValueTask<int> SearcherLua(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
         var name = context.GetArgument<string>(0);
-        var fileName = await FindFile(context.Access, name, "path", context.State.FileSystem.DirectorySeparator);
+        var fileName = await FindFile(context.Access, name, "path", context.GlobalState.FileSystem.DirectorySeparator);
         if (fileName == null)
         {
             return context.Return(LuaValue.Nil);
         }
 
-        return context.Return(await context.State.LoadFileAsync(fileName, "bt", null, cancellationToken));
+        return context.Return(await context.GlobalState.LoadFileAsync(fileName, "bt", null, cancellationToken));
     }
 }

+ 48 - 48
src/Lua/Standard/OpenLibsExtensions.cs

@@ -5,17 +5,17 @@ namespace Lua.Standard;
 
 public static class OpenLibsExtensions
 {
-    public static void OpenBasicLibrary(this LuaState state)
+    public static void OpenBasicLibrary(this LuaGlobalState globalState)
     {
-        state.Environment["_G"] = state.Environment;
-        state.Environment["_VERSION"] = "Lua 5.2";
+        globalState.Environment["_G"] = globalState.Environment;
+        globalState.Environment["_VERSION"] = "Lua 5.2";
         foreach (var func in BasicLibrary.Instance.Functions)
         {
-            state.Environment[func.Name] = func;
+            globalState.Environment[func.Name] = func;
         }
     }
 
-    public static void OpenBitwiseLibrary(this LuaState state)
+    public static void OpenBitwiseLibrary(this LuaGlobalState globalState)
     {
         LuaTable bit32 = new(0, BitwiseLibrary.Instance.Functions.Length);
         foreach (var func in BitwiseLibrary.Instance.Functions)
@@ -23,11 +23,11 @@ public static class OpenLibsExtensions
             bit32[func.Name] = func.Func;
         }
 
-        state.Environment["bit32"] = bit32;
-        state.LoadedModules["bit32"] = bit32;
+        globalState.Environment["bit32"] = bit32;
+        globalState.LoadedModules["bit32"] = bit32;
     }
 
-    public static void OpenCoroutineLibrary(this LuaState state)
+    public static void OpenCoroutineLibrary(this LuaGlobalState globalState)
     {
         LuaTable coroutine = new(0, CoroutineLibrary.Instance.Functions.Length);
         foreach (var func in CoroutineLibrary.Instance.Functions)
@@ -35,10 +35,10 @@ public static class OpenLibsExtensions
             coroutine[func.Name] = func.Func;
         }
 
-        state.Environment["coroutine"] = coroutine;
+        globalState.Environment["coroutine"] = coroutine;
     }
 
-    public static void OpenIOLibrary(this LuaState state)
+    public static void OpenIOLibrary(this LuaGlobalState globalState)
     {
         LuaTable io = new(0, IOLibrary.Instance.Functions.Length);
         foreach (var func in IOLibrary.Instance.Functions)
@@ -46,8 +46,8 @@ public static class OpenLibsExtensions
             io[func.Name] = func.Func;
         }
 
-        var registry = state.Registry;
-        var standardIO = state.StandardIO;
+        var registry = globalState.Registry;
+        var standardIO = globalState.StandardIO;
         LuaValue stdin = new(new FileHandle(standardIO.Input));
         LuaValue stdout = new(new FileHandle(standardIO.Output));
         LuaValue stderr = new(new FileHandle(standardIO.Error));
@@ -57,13 +57,13 @@ public static class OpenLibsExtensions
         io["stdout"] = stdout;
         io["stderr"] = stderr;
 
-        state.Environment["io"] = io;
-        state.LoadedModules["io"] = io;
+        globalState.Environment["io"] = io;
+        globalState.LoadedModules["io"] = io;
     }
 
-    public static void OpenMathLibrary(this LuaState state)
+    public static void OpenMathLibrary(this LuaGlobalState globalState)
     {
-        state.Environment[MathematicsLibrary.RandomInstanceKey] = new(new MathematicsLibrary.RandomUserData(new()));
+        globalState.Environment[MathematicsLibrary.RandomInstanceKey] = new(new MathematicsLibrary.RandomUserData(new()));
 
         LuaTable math = new(0, MathematicsLibrary.Instance.Functions.Length);
         foreach (var func in MathematicsLibrary.Instance.Functions)
@@ -74,15 +74,15 @@ public static class OpenLibsExtensions
         math["pi"] = Math.PI;
         math["huge"] = double.PositiveInfinity;
 
-        state.Environment["math"] = math;
-        state.LoadedModules["math"] = math;
+        globalState.Environment["math"] = math;
+        globalState.LoadedModules["math"] = math;
     }
 
-    public static void OpenModuleLibrary(this LuaState state)
+    public static void OpenModuleLibrary(this LuaGlobalState globalState)
     {
         LuaTable package = new(0, 8);
-        package["loaded"] = state.LoadedModules;
-        package["preload"] = state.PreloadModules;
+        package["loaded"] = globalState.LoadedModules;
+        package["preload"] = globalState.PreloadModules;
         var moduleLibrary = ModuleLibrary.Instance;
         LuaTable searchers = new();
         searchers[1] = new LuaFunction("preload", moduleLibrary.SearcherPreload);
@@ -91,11 +91,11 @@ public static class OpenLibsExtensions
         package["path"] = "?.lua";
         package["searchpath"] = moduleLibrary.SearchPathFunction;
         package["config"] = $"{Path.DirectorySeparatorChar}\n;\n?\n!\n-";
-        state.Environment["package"] = package;
-        state.Environment["require"] = moduleLibrary.RequireFunction;
+        globalState.Environment["package"] = package;
+        globalState.Environment["require"] = moduleLibrary.RequireFunction;
     }
 
-    public static void OpenOperatingSystemLibrary(this LuaState state)
+    public static void OpenOperatingSystemLibrary(this LuaGlobalState globalState)
     {
         LuaTable os = new(0, OperatingSystemLibrary.Instance.Functions.Length);
         foreach (var func in OperatingSystemLibrary.Instance.Functions)
@@ -103,11 +103,11 @@ public static class OpenLibsExtensions
             os[func.Name] = func.Func;
         }
 
-        state.Environment["os"] = os;
-        state.LoadedModules["os"] = os;
+        globalState.Environment["os"] = os;
+        globalState.LoadedModules["os"] = os;
     }
 
-    public static void OpenStringLibrary(this LuaState state)
+    public static void OpenStringLibrary(this LuaGlobalState globalState)
     {
         LuaTable @string = new(0, StringLibrary.Instance.Functions.Length);
         foreach (var func in StringLibrary.Instance.Functions)
@@ -115,15 +115,15 @@ public static class OpenLibsExtensions
             @string[func.Name] = func.Func;
         }
 
-        state.Environment["string"] = @string;
-        state.LoadedModules["string"] = @string;
+        globalState.Environment["string"] = @string;
+        globalState.LoadedModules["string"] = @string;
 
         // set __index
         LuaValue key = new("");
-        if (!state.TryGetMetatable(key, out var metatable))
+        if (!globalState.TryGetMetatable(key, out var metatable))
         {
             metatable = new();
-            state.SetMetatable(key, metatable);
+            globalState.SetMetatable(key, metatable);
         }
 
         metatable[Metamethods.Index] = new LuaFunction("index", (context, cancellationToken) =>
@@ -134,7 +134,7 @@ public static class OpenLibsExtensions
         });
     }
 
-    public static void OpenTableLibrary(this LuaState state)
+    public static void OpenTableLibrary(this LuaGlobalState globalState)
     {
         LuaTable table = new(0, TableLibrary.Instance.Functions.Length);
         foreach (var func in TableLibrary.Instance.Functions)
@@ -142,11 +142,11 @@ public static class OpenLibsExtensions
             table[func.Name] = func.Func;
         }
 
-        state.Environment["table"] = table;
-        state.LoadedModules["table"] = table;
+        globalState.Environment["table"] = table;
+        globalState.LoadedModules["table"] = table;
     }
 
-    public static void OpenDebugLibrary(this LuaState state)
+    public static void OpenDebugLibrary(this LuaGlobalState globalState)
     {
         LuaTable debug = new(0, DebugLibrary.Instance.Functions.Length);
         foreach (var func in DebugLibrary.Instance.Functions)
@@ -154,21 +154,21 @@ public static class OpenLibsExtensions
             debug[func.Name] = func.Func;
         }
 
-        state.Environment["debug"] = debug;
-        state.LoadedModules["debug"] = debug;
+        globalState.Environment["debug"] = debug;
+        globalState.LoadedModules["debug"] = debug;
     }
 
-    public static void OpenStandardLibraries(this LuaState state)
+    public static void OpenStandardLibraries(this LuaGlobalState globalState)
     {
-        state.OpenBasicLibrary();
-        state.OpenBitwiseLibrary();
-        state.OpenCoroutineLibrary();
-        state.OpenIOLibrary();
-        state.OpenMathLibrary();
-        state.OpenModuleLibrary();
-        state.OpenOperatingSystemLibrary();
-        state.OpenStringLibrary();
-        state.OpenTableLibrary();
-        state.OpenDebugLibrary();
+        globalState.OpenBasicLibrary();
+        globalState.OpenBitwiseLibrary();
+        globalState.OpenCoroutineLibrary();
+        globalState.OpenIOLibrary();
+        globalState.OpenMathLibrary();
+        globalState.OpenModuleLibrary();
+        globalState.OpenOperatingSystemLibrary();
+        globalState.OpenStringLibrary();
+        globalState.OpenTableLibrary();
+        globalState.OpenDebugLibrary();
     }
 }

+ 12 - 12
src/Lua/Standard/OperatingSystemLibrary.cs

@@ -28,7 +28,7 @@ public sealed class OperatingSystemLibrary
 
     public ValueTask<int> Clock(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
-        return new(context.Return(context.State.OsEnvironment.GetTotalProcessorTime()));
+        return new(context.Return(context.GlobalState.OsEnvironment.GetTotalProcessorTime()));
     }
 
     public ValueTask<int> Date(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
@@ -45,7 +45,7 @@ public sealed class OperatingSystemLibrary
         }
         else
         {
-            now = context.State.TimeProvider.GetUtcNow().DateTime;
+            now = context.GlobalState.TimeProvider.GetUtcNow().DateTime;
         }
 
         var isDst = false;
@@ -55,7 +55,7 @@ public sealed class OperatingSystemLibrary
         }
         else
         {
-            now = context.State.TimeProvider.GetLocalNow().DateTime;
+            now = context.GlobalState.TimeProvider.GetLocalNow().DateTime;
             isDst = now.IsDaylightSavingTime();
         }
 
@@ -78,7 +78,7 @@ public sealed class OperatingSystemLibrary
         }
         else
         {
-            return new(context.Return(DateTimeHelper.StrFTime(context.Thread, format, now)));
+            return new(context.Return(DateTimeHelper.StrFTime(context.State, format, now)));
         }
     }
 
@@ -121,18 +121,18 @@ public sealed class OperatingSystemLibrary
             }
             else
             {
-                LuaRuntimeException.BadArgument(context.Thread, 1, LuaValueType.Nil, code.Type);
+                LuaRuntimeException.BadArgument(context.State, 1, LuaValueType.Nil, code.Type);
             }
         }
 
-        await context.State.OsEnvironment.Exit(exitCode, cancellationToken);
+        await context.GlobalState.OsEnvironment.Exit(exitCode, cancellationToken);
         throw new InvalidOperationException("Unreachable code.. reached.");
     }
 
     public ValueTask<int> GetEnv(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
         var variable = context.GetArgument<string>(0);
-        return new(context.Return(context.State.OsEnvironment.GetEnvironmentVariable(variable) ?? LuaValue.Nil));
+        return new(context.Return(context.GlobalState.OsEnvironment.GetEnvironmentVariable(variable) ?? LuaValue.Nil));
     }
 
     public async ValueTask<int> Remove(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
@@ -140,7 +140,7 @@ public sealed class OperatingSystemLibrary
         var fileName = context.GetArgument<string>(0);
         try
         {
-            await context.State.FileSystem.Remove(fileName, cancellationToken);
+            await context.GlobalState.FileSystem.Remove(fileName, cancellationToken);
             return context.Return(true);
         }
         catch (IOException ex)
@@ -155,7 +155,7 @@ public sealed class OperatingSystemLibrary
         var newName = context.GetArgument<string>(1);
         try
         {
-            await context.State.FileSystem.Rename(oldName, newName, cancellationToken);
+            await context.GlobalState.FileSystem.Rename(oldName, newName, cancellationToken);
             return context.Return(true);
         }
         catch (IOException ex)
@@ -175,17 +175,17 @@ public sealed class OperatingSystemLibrary
         if (context.HasArgument(0))
         {
             var table = context.GetArgument<LuaTable>(0);
-            var date = DateTimeHelper.ParseTimeTable(context.Thread, table);
+            var date = DateTimeHelper.ParseTimeTable(context.State, table);
             return new(context.Return(DateTimeHelper.GetUnixTime(date)));
         }
         else
         {
-            return new(context.Return(DateTimeHelper.GetUnixTime(context.State.TimeProvider.GetUtcNow().DateTime)));
+            return new(context.Return(DateTimeHelper.GetUnixTime(context.GlobalState.TimeProvider.GetUtcNow().DateTime)));
         }
     }
 
     public ValueTask<int> TmpName(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
-        return new(context.Return(context.State.FileSystem.GetTempFileName()));
+        return new(context.Return(context.GlobalState.FileSystem.GetTempFileName()));
     }
 }

+ 27 - 27
src/Lua/Standard/StringLibrary.cs

@@ -45,8 +45,8 @@ public sealed class StringLibrary
             ? context.GetArgument<double>(2)
             : i;
 
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 2, i);
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 3, j);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 2, i);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 3, j);
 
         var span = StringHelper.Slice(s, (int)i, (int)j);
         var buffer = context.GetReturnBuffer(span.Length);
@@ -69,7 +69,7 @@ public sealed class StringLibrary
         for (var i = 0; i < context.ArgumentCount; i++)
         {
             var arg = context.GetArgument<double>(i);
-            LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, i + 1, arg);
+            LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, i + 1, arg);
             builder.Append((char)arg);
         }
 
@@ -89,7 +89,7 @@ public sealed class StringLibrary
     public async ValueTask<int> Format(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
     {
         var format = context.GetArgument<string>(0);
-        var stack = context.Thread.Stack;
+        var stack = context.State.Stack;
         // TODO: pooling StringBuilder
         StringBuilder builder = new(format.Length * 2);
         var parameterIndex = 1;
@@ -124,7 +124,7 @@ public sealed class StringLibrary
                         case '-':
                             if (leftJustify)
                             {
-                                throw new LuaRuntimeException(context.Thread, "invalid format (repeated flags)");
+                                throw new LuaRuntimeException(context.State, "invalid format (repeated flags)");
                             }
 
                             leftJustify = true;
@@ -132,7 +132,7 @@ public sealed class StringLibrary
                         case '+':
                             if (plusSign)
                             {
-                                throw new LuaRuntimeException(context.Thread, "invalid format (repeated flags)");
+                                throw new LuaRuntimeException(context.State, "invalid format (repeated flags)");
                             }
 
                             plusSign = true;
@@ -140,7 +140,7 @@ public sealed class StringLibrary
                         case '0':
                             if (zeroPadding)
                             {
-                                throw new LuaRuntimeException(context.Thread, "invalid format (repeated flags)");
+                                throw new LuaRuntimeException(context.State, "invalid format (repeated flags)");
                             }
 
                             zeroPadding = true;
@@ -148,7 +148,7 @@ public sealed class StringLibrary
                         case '#':
                             if (alternateForm)
                             {
-                                throw new LuaRuntimeException(context.Thread, "invalid format (repeated flags)");
+                                throw new LuaRuntimeException(context.State, "invalid format (repeated flags)");
                             }
 
                             alternateForm = true;
@@ -156,7 +156,7 @@ public sealed class StringLibrary
                         case ' ':
                             if (blank)
                             {
-                                throw new LuaRuntimeException(context.Thread, "invalid format (repeated flags)");
+                                throw new LuaRuntimeException(context.State, "invalid format (repeated flags)");
                             }
 
                             blank = true;
@@ -182,7 +182,7 @@ public sealed class StringLibrary
 
                     if (char.IsDigit(format[i]))
                     {
-                        throw new LuaRuntimeException(context.Thread, "invalid format (width or precision too long)");
+                        throw new LuaRuntimeException(context.State, "invalid format (width or precision too long)");
                     }
 
                     width = int.Parse(format.AsSpan()[start..i]);
@@ -205,7 +205,7 @@ public sealed class StringLibrary
 
                     if (char.IsDigit(format[i]))
                     {
-                        throw new LuaRuntimeException(context.Thread, "invalid format (width or precision too long)");
+                        throw new LuaRuntimeException(context.State, "invalid format (width or precision too long)");
                     }
 
                     precision = int.Parse(format.AsSpan()[start..i]);
@@ -216,7 +216,7 @@ public sealed class StringLibrary
 
                 if (context.ArgumentCount <= parameterIndex)
                 {
-                    throw new LuaRuntimeException(context.Thread, $"bad argument #{parameterIndex + 1} to 'format' (no value)");
+                    throw new LuaRuntimeException(context.State, $"bad argument #{parameterIndex + 1} to 'format' (no value)");
                 }
 
                 var parameter = context.GetArgument(parameterIndex++);
@@ -231,7 +231,7 @@ public sealed class StringLibrary
                     case 'G':
                         if (!parameter.TryRead<double>(out var f))
                         {
-                            LuaRuntimeException.BadArgument(context.Thread, parameterIndex + 1, LuaValueType.Number, parameter.Type);
+                            LuaRuntimeException.BadArgument(context.State, parameterIndex + 1, LuaValueType.Number, parameter.Type);
                         }
 
                         switch (specifier)
@@ -322,10 +322,10 @@ public sealed class StringLibrary
                     case 'X':
                         if (!parameter.TryRead<double>(out var x))
                         {
-                            LuaRuntimeException.BadArgument(context.Thread, parameterIndex + 1, LuaValueType.Number, parameter.Type);
+                            LuaRuntimeException.BadArgument(context.State, parameterIndex + 1, LuaValueType.Number, parameter.Type);
                         }
 
-                        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, parameterIndex + 1, x);
+                        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, parameterIndex + 1, x);
 
                         switch (specifier)
                         {
@@ -380,7 +380,7 @@ public sealed class StringLibrary
 
                         break;
                     default:
-                        throw new LuaRuntimeException(context.Thread, $"invalid option '%{specifier}' to 'format'");
+                        throw new LuaRuntimeException(context.State, $"invalid option '%{specifier}' to 'format'");
                 }
 
                 // Apply blank (' ') flag for positive numbers
@@ -428,7 +428,7 @@ public sealed class StringLibrary
             var pattern = upValues[1].Read<string>();
             var start = upValues[2].Read<int>();
 
-            MatchState matchState = new(context.Thread, s, pattern);
+            MatchState matchState = new(context.State, s, pattern);
             var captures = matchState.Captures;
 
             // Check for anchor at start
@@ -500,12 +500,12 @@ public sealed class StringLibrary
             ? context.GetArgument<double>(3)
             : s.Length + 1;
 
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 4, n_arg);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 4, n_arg);
 
         var n = (int)n_arg;
 
         // Use MatchState instead of regex
-        MatchState matchState = new(context.Thread, s, pattern);
+        MatchState matchState = new(context.State, s, pattern);
         var captures = matchState.Captures;
 
         StringBuilder builder = new();
@@ -610,7 +610,7 @@ public sealed class StringLibrary
                 else if (repl.TryRead<LuaFunction>(out var func))
                 {
                     // Function call with captures as arguments
-                    var stack = context.Thread.Stack;
+                    var stack = context.State.Stack;
 
                     if (matchState.Level == 0)
                     {
@@ -643,7 +643,7 @@ public sealed class StringLibrary
                 }
                 else
                 {
-                    throw new LuaRuntimeException(context.Thread, "bad argument #3 to 'gsub' (string/function/table expected)");
+                    throw new LuaRuntimeException(context.State, "bad argument #3 to 'gsub' (string/function/table expected)");
                 }
 
                 // Handle replacement result
@@ -662,7 +662,7 @@ public sealed class StringLibrary
                 }
                 else
                 {
-                    throw new LuaRuntimeException(context.Thread, $"invalid replacement value (a {result.Type})");
+                    throw new LuaRuntimeException(context.State, $"invalid replacement value (a {result.Type})");
                 }
 
                 replaceCount++;
@@ -731,7 +731,7 @@ public sealed class StringLibrary
             ? context.GetArgument<int>(2)
             : 1;
 
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 3, init);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 3, init);
 
         // Convert to 0-based index
         if (init < 0)
@@ -772,7 +772,7 @@ public sealed class StringLibrary
 
     static ValueTask<int> PatternSearch(LuaFunctionExecutionContext context, string s, string pattern, int init, bool find)
     {
-        MatchState matchState = new(context.Thread, s, pattern);
+        MatchState matchState = new(context.State, s, pattern);
         var captures = matchState.Captures;
 
         // Check for anchor at start
@@ -847,7 +847,7 @@ public sealed class StringLibrary
             ? context.GetArgument<string>(2)
             : null;
 
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 2, n_arg);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 2, n_arg);
 
         var n = (int)n_arg;
 
@@ -882,8 +882,8 @@ public sealed class StringLibrary
             ? context.GetArgument<double>(2)
             : -1;
 
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 2, i);
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 3, j);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 2, i);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 3, j);
 
         return new(context.Return(StringHelper.Slice(s, (int)i, (int)j).ToString()));
     }

+ 13 - 13
src/Lua/Standard/TableLibrary.cs

@@ -70,7 +70,7 @@ public sealed class TableLibrary
             }
             else
             {
-                throw new LuaRuntimeException(context.Thread, $"invalid value ({value.Type}) at index {i} in table for 'concat'");
+                throw new LuaRuntimeException(context.State, $"invalid value ({value.Type}) at index {i} in table for 'concat'");
             }
 
             if (i != arg3)
@@ -94,13 +94,13 @@ public sealed class TableLibrary
             ? context.GetArgument<double>(1)
             : table.ArrayLength + 1;
 
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 2, pos_arg);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 2, pos_arg);
 
         var pos = (int)pos_arg;
 
         if (pos <= 0 || pos > table.ArrayLength + 1)
         {
-            throw new LuaRuntimeException(context.Thread, "bad argument #2 to 'insert' (position out of bounds)");
+            throw new LuaRuntimeException(context.State, "bad argument #2 to 'insert' (position out of bounds)");
         }
 
         table.Insert(pos, value);
@@ -129,7 +129,7 @@ public sealed class TableLibrary
             ? context.GetArgument<double>(1)
             : table.ArrayLength;
 
-        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 2, n_arg);
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, 2, n_arg);
 
         var n = (int)n_arg;
 
@@ -140,7 +140,7 @@ public sealed class TableLibrary
 
         if (n <= 0 || n > table.GetArraySpan().Length)
         {
-            throw new LuaRuntimeException(context.Thread, "bad argument #2 to 'remove' (position out of bounds)");
+            throw new LuaRuntimeException(context.State, "bad argument #2 to 'remove' (position out of bounds)");
         }
 
         return new(context.Return(table.RemoveAt(n)));
@@ -151,13 +151,13 @@ public sealed class TableLibrary
         var arg0 = context.GetArgument<LuaTable>(0);
         var arg1 = context.HasArgument(1)
             ? context.GetArgument<LuaFunction>(1)
-            : new LuaClosure(context.Thread, defaultComparer);
+            : new LuaClosure(context.State, defaultComparer);
 
         // discard extra  arguments
         context = context with { ArgumentCount = 2 };
-        context.Thread.Stack.PopUntil(context.FrameBase + 2);
+        context.State.Stack.PopUntil(context.FrameBase + 2);
 
-        context.Thread.PushCallStackFrame(new() { Base = context.FrameBase, ReturnBase = context.ReturnFrameBase, VariableArgumentCount = 0, Function = arg1 });
+        context.State.PushCallStackFrame(new() { Base = context.FrameBase, ReturnBase = context.ReturnFrameBase, VariableArgumentCount = 0, Function = arg1 });
         try
         {
             await QuickSortAsync(context, arg0.GetArrayMemory(), 0, arg0.ArrayLength - 1, arg1, cancellationToken);
@@ -165,7 +165,7 @@ public sealed class TableLibrary
         }
         finally
         {
-            context.Thread.PopCallStackFrameWithStackPop();
+            context.State.PopCallStackFrameWithStackPop();
         }
     }
 
@@ -183,23 +183,23 @@ public sealed class TableLibrary
     {
         var pivot = memory.Span[high];
         var i = low - 1;
-        var access = context.Thread.CurrentAccess;
+        var access = context.State.CurrentAccess;
 
         for (var j = low; j < high; j++)
         {
-            var stack = context.Thread.Stack;
+            var stack = context.State.Stack;
             var top = stack.Count;
             stack.Push(memory.Span[j]);
             stack.Push(pivot);
             await access.RunAsync(comparer, 2, cancellationToken);
 
-            if (context.Thread.Stack.Get(top).ToBoolean())
+            if (context.State.Stack.Get(top).ToBoolean())
             {
                 i++;
                 Swap(memory.Span, i, j);
             }
 
-            context.Thread.Stack.PopUntil(top);
+            context.State.Stack.PopUntil(top);
         }
 
         Swap(memory.Span, i + 1, high);

+ 2 - 2
tests/Lua.Tests/AbstractFileTests.cs

@@ -30,7 +30,7 @@ public class AbstractFileTests
     {
         var fileContent = "line1\nline2\r\nline3";
         var fileSystem = new ReadOnlyFileSystem(new() { { "test.txt", fileContent } });
-        var state = LuaState.Create(new(
+        var state = LuaGlobalState.Create(new(
             fileSystem: fileSystem,
             osEnvironment: null!,
             standardIO: new ConsoleStandardIO(),
@@ -64,7 +64,7 @@ public class AbstractFileTests
     {
         var fileContent = "Hello, World!";
         var fileSystem = new ReadOnlyFileSystem(new() { { "test.txt", fileContent } });
-        var state = LuaState.Create(new(
+        var state = LuaGlobalState.Create(new(
             fileSystem: fileSystem,
             osEnvironment: null!,
             standardIO: new ConsoleStandardIO(),

+ 7 - 7
tests/Lua.Tests/AsyncTests.cs

@@ -4,15 +4,15 @@ namespace Lua.Tests;
 
 public class AsyncTests
 {
-    LuaState state = default!;
+    LuaGlobalState globalState = default!;
 
     [SetUp]
     public void SetUp()
     {
-        state = LuaState.Create();
-        state.OpenStandardLibraries();
-        var assert = state.Environment["assert"].Read<LuaFunction>();
-        state.Environment["assert"] = new LuaFunction("assert_with_wait",
+        globalState = LuaGlobalState.Create();
+        globalState.OpenStandardLibraries();
+        var assert = globalState.Environment["assert"].Read<LuaFunction>();
+        globalState.Environment["assert"] = new LuaFunction("assert_with_wait",
             async (context, ct) =>
             {
                 await Task.Delay(1, ct);
@@ -26,7 +26,7 @@ public class AsyncTests
                         message = context.GetArgument<string>(1);
                     }
 
-                    throw new LuaAssertionException(context.Thread, message);
+                    throw new LuaAssertionException(context.State, message);
                 }
 
                 return context.Return(context.Arguments);
@@ -42,7 +42,7 @@ public class AsyncTests
         var path = FileHelper.GetAbsolutePath(file);
         try
         {
-            await state.DoFileAsync(path);
+            await globalState.DoFileAsync(path);
         }
         catch (LuaRuntimeException e)
         {

+ 13 - 13
tests/Lua.Tests/CancellationTest.cs

@@ -5,15 +5,15 @@ namespace Lua.Tests;
 
 public class CancellationTest
 {
-    LuaState state = default!;
+    LuaGlobalState globalState = default!;
 
     [SetUp]
     public void SetUp()
     {
-        state = LuaState.Create();
-        state.OpenStandardLibraries();
+        globalState = LuaGlobalState.Create();
+        globalState.OpenStandardLibraries();
 
-        state.Environment["assert"] = new LuaFunction("assert_with_wait",
+        globalState.Environment["assert"] = new LuaFunction("assert_with_wait",
             async (context, ct) =>
             {
                 await Task.Delay(1, ct);
@@ -27,19 +27,19 @@ public class CancellationTest
                         message = context.GetArgument<string>(1);
                     }
 
-                    throw new LuaAssertionException(context.Thread, message);
+                    throw new LuaAssertionException(context.State, message);
                 }
 
                 return context.Return(context.Arguments);
             });
-        state.Environment["sleep"] = new LuaFunction("sleep",
+        globalState.Environment["sleep"] = new LuaFunction("sleep",
             (context, _) =>
             {
                 Thread.Sleep(context.GetArgument<int>(0));
 
                 return new(context.Return());
             });
-        state.Environment["wait"] = new LuaFunction("wait",
+        globalState.Environment["wait"] = new LuaFunction("wait",
             async (context, ct) =>
             {
                 await Task.Delay(context.GetArgument<int>(0), ct);
@@ -61,7 +61,7 @@ public class CancellationTest
 
         try
         {
-            await state.DoStringAsync(source, "@test.lua", cancellationTokenSource.Token);
+            await globalState.DoStringAsync(source, "@test.lua", cancellationTokenSource.Token);
             Assert.Fail("Expected TaskCanceledException was not thrown.");
         }
         catch (Exception e)
@@ -90,7 +90,7 @@ public class CancellationTest
 
         try
         {
-            await state.DoStringAsync(source, "@test.lua", cancellationTokenSource.Token);
+            await globalState.DoStringAsync(source, "@test.lua", cancellationTokenSource.Token);
             Assert.Fail("Expected TaskCanceledException was not thrown.");
         }
         catch (Exception e)
@@ -123,7 +123,7 @@ public class CancellationTest
         });
         try
         {
-            var r = await state.DoStringAsync(source, "@test.lua", cancellationTokenSource.Token);
+            var r = await globalState.DoStringAsync(source, "@test.lua", cancellationTokenSource.Token);
             Console.WriteLine(r[0]);
             Assert.Fail("Expected TaskCanceledException was not thrown.");
         }
@@ -160,7 +160,7 @@ public class CancellationTest
         });
         try
         {
-            var r = await state.DoStringAsync(source, "@test.lua", cancellationTokenSource.Token);
+            var r = await globalState.DoStringAsync(source, "@test.lua", cancellationTokenSource.Token);
             Console.WriteLine(r[0]);
             Assert.Fail("Expected TaskCanceledException was not thrown.");
         }
@@ -191,7 +191,7 @@ public class CancellationTest
                      """;
         var cancellationTokenSource = new CancellationTokenSource();
         var sw = Stopwatch.StartNew();
-        state.MainThread.SetHook(new("timeout", async (context, cancellationToken) =>
+        globalState.MainThread.SetHook(new("timeout", async (context, cancellationToken) =>
         {
             if (sw.ElapsedMilliseconds > 100)
             {
@@ -208,7 +208,7 @@ public class CancellationTest
         });
         try
         {
-            var r = await state.DoStringAsync(source, "@test.lua", cancellationTokenSource.Token);
+            var r = await globalState.DoStringAsync(source, "@test.lua", cancellationTokenSource.Token);
             Console.WriteLine(r[0]);
             Assert.Fail("Expected TaskCanceledException was not thrown.");
         }

+ 1 - 1
tests/Lua.Tests/ConditionalsTests.cs

@@ -12,7 +12,7 @@ end
 
 return clamp(0, 1, 25), clamp(10, 1, 25), clamp(30, 1, 25)
 ";
-        var result = await LuaState.Create().DoStringAsync(source);
+        var result = await LuaGlobalState.Create().DoStringAsync(source);
 
         Assert.That(result, Has.Length.EqualTo(3));
         Assert.That(result[0], Is.EqualTo(new LuaValue(1)));

+ 5 - 5
tests/Lua.Tests/LocalTests.cs

@@ -8,7 +8,7 @@ public class LocalTests
         var source = @"
 local function f(x) x = nil; return x end
 return f(10)";
-        var result = await LuaState.Create().DoStringAsync(source);
+        var result = await LuaGlobalState.Create().DoStringAsync(source);
 
         Assert.That(result, Has.Length.EqualTo(1));
         Assert.That(result[0], Is.EqualTo(LuaValue.Nil));
@@ -20,7 +20,7 @@ return f(10)";
         var source = @"
 local function f() local x; return x end
 return f(10)";
-        var result = await LuaState.Create().DoStringAsync(source);
+        var result = await LuaGlobalState.Create().DoStringAsync(source);
 
         Assert.That(result, Has.Length.EqualTo(1));
         Assert.That(result[0], Is.EqualTo(LuaValue.Nil));
@@ -32,7 +32,7 @@ return f(10)";
         var source = @"
 local function f(x) x = nil; local y; return x, y end
 return f(10)";
-        var result = await LuaState.Create().DoStringAsync(source);
+        var result = await LuaGlobalState.Create().DoStringAsync(source);
 
         Assert.That(result, Has.Length.EqualTo(2));
         Assert.Multiple(() =>
@@ -46,7 +46,7 @@ return f(10)";
     public async Task Test_LocalVariable_1()
     {
         var source = "local i = 10; do local i = 100; return i end";
-        var result = await LuaState.Create().DoStringAsync(source);
+        var result = await LuaGlobalState.Create().DoStringAsync(source);
 
         Assert.That(result, Has.Length.EqualTo(1));
         Assert.That(result[0], Is.EqualTo(new LuaValue(100)));
@@ -59,7 +59,7 @@ return f(10)";
 local i = 10
 do local i = 100 end
 return i";
-        var result = await LuaState.Create().DoStringAsync(source);
+        var result = await LuaGlobalState.Create().DoStringAsync(source);
 
         Assert.That(result, Has.Length.EqualTo(1));
         Assert.That(result[0], Is.EqualTo(new LuaValue(10)));

+ 3 - 3
tests/Lua.Tests/LoopTests.cs

@@ -11,7 +11,7 @@ for i = 1, 10 do
     n = n + i
 end
 return n";
-        var result = await LuaState.Create().DoStringAsync(source);
+        var result = await LuaGlobalState.Create().DoStringAsync(source);
 
         Assert.That(result, Has.Length.EqualTo(1));
         Assert.That(result[0], Is.EqualTo(new LuaValue(55)));
@@ -26,7 +26,7 @@ for i = 0, 10, 2 do
     n = n + i
 end
 return n";
-        var result = await LuaState.Create().DoStringAsync(source);
+        var result = await LuaGlobalState.Create().DoStringAsync(source);
 
         Assert.That(result, Has.Length.EqualTo(1));
         Assert.That(result[0], Is.EqualTo(new LuaValue(30)));
@@ -41,7 +41,7 @@ while n < 100 do
     n = n + 1
 end
 return n";
-        var result = await LuaState.Create().DoStringAsync(source);
+        var result = await LuaGlobalState.Create().DoStringAsync(source);
 
         Assert.That(result, Has.Length.EqualTo(1));
         Assert.That(result[0], Is.EqualTo(new LuaValue(100)));

+ 12 - 12
tests/Lua.Tests/LuaApiTests.cs

@@ -5,13 +5,13 @@ namespace Lua.Tests;
 
 public class LuaApiTests
 {
-    LuaState state = default!;
+    LuaGlobalState globalState = default!;
 
     [OneTimeSetUp]
     public void SetUp()
     {
-        state = LuaState.Create();
-        state.OpenStandardLibraries();
+        globalState = LuaGlobalState.Create();
+        globalState.OpenStandardLibraries();
     }
 
     [Test]
@@ -34,7 +34,7 @@ public class LuaApiTests
                      setmetatable(a, metatable)
                      return a, b
                      """;
-        var access = state.RootAccess;
+        var access = globalState.RootAccess;
         var result = await access.DoStringAsync(source);
         var a = result[0].Read<LuaTable>();
         var b = result[1].Read<LuaTable>();
@@ -68,7 +68,7 @@ public class LuaApiTests
                      setmetatable(a, metatable)
                      return a
                      """;
-        var access = state.RootAccess;
+        var access = globalState.RootAccess;
 
         var result = await access.DoStringAsync(source);
         var a = result[0].Read<LuaTable>();
@@ -106,7 +106,7 @@ public class LuaApiTests
                      setmetatable(a, metatable)
                      return a, b, c
                      """;
-        var access = state.RootAccess;
+        var access = globalState.RootAccess;
         var result = await access.DoStringAsync(source);
         var a = result[0].Read<LuaTable>();
         var b = result[1].Read<LuaTable>();
@@ -129,11 +129,11 @@ public class LuaApiTests
                      setmetatable(a, metatable)
                      return a
                      """;
-        var access = state.RootAccess;
+        var access = globalState.RootAccess;
         var result = await access.DoStringAsync(source);
         var a = result[0].Read<LuaTable>();
         Assert.That(await access.GetTable(a, "x"), Is.EqualTo(new LuaValue(1)));
-        a.Metatable!["__index"] = state.DoStringAsync("return function(a,b) return b end").Result[0];
+        a.Metatable!["__index"] = globalState.DoStringAsync("return function(a,b) return b end").Result[0];
         Assert.That(await access.GetTable(a, "x"), Is.EqualTo(new LuaValue("x")));
     }
 
@@ -150,7 +150,7 @@ public class LuaApiTests
                      setmetatable(a, metatable)
                      return a
                      """;
-        var access = state.RootAccess;
+        var access = globalState.RootAccess;
         var result = await access.DoStringAsync(source);
         var a = result[0].Read<LuaTable>();
         await access.SetTable(a, "a", "b");
@@ -183,7 +183,7 @@ setmetatable(c, metatable)
 
 return a,b,c
 ";
-        var access = state.RootAccess;
+        var access = globalState.RootAccess;
         var result = await access.DoStringAsync(source);
         Assert.That(result, Has.Length.EqualTo(3));
 
@@ -229,7 +229,7 @@ return a,b,c
                      local c ={name ="c"}
                      return a,b,c
                      """;
-        var access = state.RootAccess;
+        var access = globalState.RootAccess;
         var result = await access.DoStringAsync(source);
         var a = result[0];
         var b = result[1];
@@ -272,7 +272,7 @@ return a,b,c
                      local c ={name ="c"}
                      return a,b,c
                      """;
-        var access = state.RootAccess;
+        var access = globalState.RootAccess;
         var result = await access.DoStringAsync(source);
         var a = result[0];
         var b = result[1];

+ 8 - 8
tests/Lua.Tests/LuaObjectTests.cs

@@ -60,7 +60,7 @@ public class LuaObjectTests
     {
         var userData = new TestUserData { Property = 1 };
 
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.Environment["test"] = userData;
         var results = await state.DoStringAsync("return test.Property");
 
@@ -73,7 +73,7 @@ public class LuaObjectTests
     {
         var userData = new TestUserData { PropertyWithName = "foo" };
 
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.Environment["test"] = userData;
         var results = await state.DoStringAsync("return test.p2");
 
@@ -86,7 +86,7 @@ public class LuaObjectTests
     {
         var userData = new TestUserData();
 
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.Environment["test"] = userData;
         var results = await state.DoStringAsync("return test.MethodVoid()");
 
@@ -98,7 +98,7 @@ public class LuaObjectTests
     {
         var userData = new TestUserData();
 
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.Environment["test"] = userData;
         var results = await state.DoStringAsync("return test.MethodAsync()");
 
@@ -110,7 +110,7 @@ public class LuaObjectTests
     {
         var userData = new TestUserData();
 
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.Environment["test"] = userData;
         var results = await state.DoStringAsync("return test.StaticMethodWithReturnValue(1, 2)");
 
@@ -123,7 +123,7 @@ public class LuaObjectTests
     {
         var userData = new TestUserData { Property = 1 };
 
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.Environment["test"] = userData;
         var results = await state.DoStringAsync("return test:InstanceMethodWithReturnValue()");
 
@@ -136,7 +136,7 @@ public class LuaObjectTests
     {
         var userData = new TestUserData { Property = 1 };
 
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.Environment["test"] = userData;
         var results = await state.DoStringAsync("return test:InstanceMethodWithReturnValueAsync(2)");
 
@@ -149,7 +149,7 @@ public class LuaObjectTests
     {
         var userData = new TestUserData();
 
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenBasicLibrary();
         state.Environment["test"] = userData;
         var results = await state.DoStringAsync("""

+ 1 - 1
tests/Lua.Tests/LuaTests.cs

@@ -29,7 +29,7 @@ public class LuaTests
     [TestCase("tests-lua/verybig.lua")]
     public async Task Test_Lua(string file)
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.Platform.StandardIO = new TestStandardIO();
         state.OpenStandardLibraries();
         var path = FileHelper.GetAbsolutePath(file);

+ 11 - 11
tests/Lua.Tests/MetatableTests.cs

@@ -4,13 +4,13 @@ namespace Lua.Tests;
 
 public class MetatableTests
 {
-    LuaState state = default!;
+    LuaGlobalState globalState = default!;
 
     [OneTimeSetUp]
     public void SetUp()
     {
-        state = LuaState.Create();
-        state.OpenStandardLibraries();
+        globalState = LuaGlobalState.Create();
+        globalState.OpenStandardLibraries();
     }
 
     [Test]
@@ -35,7 +35,7 @@ setmetatable(a, metatable)
 return a + b
 ";
 
-        var result = await state.DoStringAsync(source);
+        var result = await globalState.DoStringAsync(source);
         Assert.That(result, Has.Length.EqualTo(1));
 
         var table = result[0].Read<LuaTable>();
@@ -69,7 +69,7 @@ setmetatable(a, metatable)
 return a .. b
 ";
 
-        var result = await state.DoStringAsync(source);
+        var result = await globalState.DoStringAsync(source);
         Assert.That(result, Has.Length.EqualTo(1));
 
         var table = result[0].Read<LuaTable>();
@@ -97,7 +97,7 @@ assert(a.x == nil)
 metatable.__index= function(a,b) return b end
 assert(a.x == 'x')
 ";
-        await state.DoStringAsync(source);
+        await globalState.DoStringAsync(source);
     }
 
     [Test]
@@ -118,7 +118,7 @@ a.x = 2
 assert(a.x == nil)
 assert(metatable.__newindex.x == 2)
 ";
-        await state.DoStringAsync(source);
+        await globalState.DoStringAsync(source);
     }
 
     [Test]
@@ -141,7 +141,7 @@ end
 tail(a, 3)
 assert(tail(a, 3) == 4)
 ";
-        await state.DoStringAsync(source);
+        await globalState.DoStringAsync(source);
     }
 
     [Test]
@@ -169,7 +169,7 @@ t =setmetatable({},{__call = a})
 for i in t do 
 end
 ";
-        await state.DoStringAsync(source);
+        await globalState.DoStringAsync(source);
     }
 
     [Test]
@@ -184,7 +184,7 @@ end
                      debug.sethook()
                      return t
                      """;
-        var r = await state.DoStringAsync(source);
+        var r = await globalState.DoStringAsync(source);
         Assert.That(r, Has.Length.EqualTo(1));
         Assert.That(r[0].Read<LuaTable>()[1].Read<string>(), Does.Contain("stack traceback:"));
     }
@@ -211,6 +211,6 @@ end
                      assert((b + c)== "abc")
                      assert((b .. c)== "abc")
                      """;
-        await state.DoStringAsync(source);
+        await globalState.DoStringAsync(source);
     }
 }

+ 12 - 12
tests/Lua.Tests/OperatorTests.cs

@@ -9,7 +9,7 @@ public class OperatorTests
     [TestCase(5, 10)]
     public async Task Test_Add(double a, double b)
     {
-        var result = await LuaState.Create().DoStringAsync($"return {a} + {b}");
+        var result = await LuaGlobalState.Create().DoStringAsync($"return {a} + {b}");
         Assert.That(result, Has.Length.EqualTo(1));
         Assert.That(result[0], Is.EqualTo(new LuaValue(a + b)));
     }
@@ -21,7 +21,7 @@ public class OperatorTests
     [TestCase(5, 10)]
     public async Task Test_Sub(double a, double b)
     {
-        var result = await LuaState.Create().DoStringAsync($"return {a} - {b}");
+        var result = await LuaGlobalState.Create().DoStringAsync($"return {a} - {b}");
         Assert.That(result, Has.Length.EqualTo(1));
         Assert.That(result[0], Is.EqualTo(new LuaValue(a - b)));
     }
@@ -33,7 +33,7 @@ public class OperatorTests
     [TestCase(5, 10)]
     public async Task Test_Mul(double a, double b)
     {
-        var result = await LuaState.Create().DoStringAsync($"return {a} * {b}");
+        var result = await LuaGlobalState.Create().DoStringAsync($"return {a} * {b}");
         Assert.That(result, Has.Length.EqualTo(1));
         Assert.That(result[0], Is.EqualTo(new LuaValue(a * b)));
     }
@@ -45,7 +45,7 @@ public class OperatorTests
     [TestCase(5, 10)]
     public async Task Test_Div(double a, double b)
     {
-        var result = await LuaState.Create().DoStringAsync($"return {a} / {b}");
+        var result = await LuaGlobalState.Create().DoStringAsync($"return {a} / {b}");
         Assert.That(result, Has.Length.EqualTo(1));
         Assert.That(result[0], Is.EqualTo(new LuaValue(a / b)));
     }
@@ -57,7 +57,7 @@ public class OperatorTests
     [TestCase(5, 10)]
     public async Task Test_Mod(double a, double b)
     {
-        var result = await LuaState.Create().DoStringAsync($"return {a} % {b}");
+        var result = await LuaGlobalState.Create().DoStringAsync($"return {a} % {b}");
         Assert.That(result, Has.Length.EqualTo(1));
         Assert.That(result[0], Is.EqualTo(new LuaValue(a % b)));
     }
@@ -69,7 +69,7 @@ public class OperatorTests
     [TestCase(5, 10)]
     public async Task Test_Pow(double a, double b)
     {
-        var result = await LuaState.Create().DoStringAsync($"return {a} ^ {b}");
+        var result = await LuaGlobalState.Create().DoStringAsync($"return {a} ^ {b}");
         Assert.That(result, Has.Length.EqualTo(1));
         Assert.That(result[0], Is.EqualTo(new LuaValue(Math.Pow(a, b))));
     }
@@ -81,7 +81,7 @@ public class OperatorTests
     public async Task Test_Or(bool a, bool b)
     {
         string strA = a.ToString().ToLower(), strB = b.ToString().ToLower();
-        var result = await LuaState.Create().DoStringAsync($"return {strA} or {strB}");
+        var result = await LuaGlobalState.Create().DoStringAsync($"return {strA} or {strB}");
         Assert.That(result, Has.Length.EqualTo(1));
         Assert.That(result[0], Is.EqualTo(new LuaValue(a || b)));
     }
@@ -93,7 +93,7 @@ public class OperatorTests
     public async Task Test_And(bool a, bool b)
     {
         string strA = a.ToString().ToLower(), strB = b.ToString().ToLower();
-        var result = await LuaState.Create().DoStringAsync($"return {strA} and {strB}");
+        var result = await LuaGlobalState.Create().DoStringAsync($"return {strA} and {strB}");
         Assert.That(result, Has.Length.EqualTo(1));
         Assert.That(result[0], Is.EqualTo(new LuaValue(a && b)));
     }
@@ -103,7 +103,7 @@ public class OperatorTests
     [TestCase(5, 5)]
     public async Task Test_LessThan(double a, double b)
     {
-        var result = await LuaState.Create().DoStringAsync($"return {a} < {b}");
+        var result = await LuaGlobalState.Create().DoStringAsync($"return {a} < {b}");
         Assert.That(result, Has.Length.EqualTo(1));
         Assert.That(result[0], Is.EqualTo(new LuaValue(a < b)));
     }
@@ -113,7 +113,7 @@ public class OperatorTests
     [TestCase(5, 5)]
     public async Task Test_LessThanOrEquals(double a, double b)
     {
-        var result = await LuaState.Create().DoStringAsync($"return {a} <= {b}");
+        var result = await LuaGlobalState.Create().DoStringAsync($"return {a} <= {b}");
         Assert.That(result, Has.Length.EqualTo(1));
         Assert.That(result[0], Is.EqualTo(new LuaValue(a <= b)));
     }
@@ -123,7 +123,7 @@ public class OperatorTests
     [TestCase(5, 5)]
     public async Task Test_GreaterThan(double a, double b)
     {
-        var result = await LuaState.Create().DoStringAsync($"return {a} > {b}");
+        var result = await LuaGlobalState.Create().DoStringAsync($"return {a} > {b}");
         Assert.That(result, Has.Length.EqualTo(1));
         Assert.That(result[0], Is.EqualTo(new LuaValue(a > b)));
     }
@@ -133,7 +133,7 @@ public class OperatorTests
     [TestCase(5, 5)]
     public async Task Test_GreaterThanOrEquals(double a, double b)
     {
-        var result = await LuaState.Create().DoStringAsync($"return {a} >= {b}");
+        var result = await LuaGlobalState.Create().DoStringAsync($"return {a} >= {b}");
         Assert.That(result, Has.Length.EqualTo(1));
         Assert.That(result[0], Is.EqualTo(new LuaValue(a >= b)));
     }

+ 36 - 36
tests/Lua.Tests/PatternMatchingTests.cs

@@ -7,7 +7,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringMatch_BasicPatterns()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Literal match
@@ -25,7 +25,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringMatch_CharacterClasses()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // %d - digits
@@ -51,7 +51,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringMatch_Quantifiers()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // + (one or more)
@@ -80,7 +80,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringMatch_Captures()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Single capture
@@ -108,7 +108,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringMatch_Anchors()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // ^ (start anchor)
@@ -129,7 +129,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringMatch_WithInitPosition()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Start from specific position
@@ -147,7 +147,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringMatch_SpecialPatterns()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Dot (any character)
@@ -169,7 +169,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringFind_BasicUsage()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Basic literal search
@@ -193,7 +193,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringFind_WithPatterns()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Pattern with captures
@@ -224,7 +224,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringFind_PlainSearch()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Plain search (4th parameter = true)
@@ -243,7 +243,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringFind_EdgeCases()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Empty pattern
@@ -287,7 +287,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringGMatch_BasicUsage()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
         state.OpenTableLibrary();
         // Test basic gmatch iteration
@@ -307,7 +307,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringGMatch_WithCaptures()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
         state.OpenTableLibrary();
 
@@ -328,7 +328,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringGMatch_Numbers()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
         state.OpenTableLibrary();
 
@@ -349,7 +349,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringGMatch_EmptyMatches()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
         state.OpenTableLibrary();
 
@@ -368,7 +368,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringGMatch_ComplexPatterns()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
         state.OpenTableLibrary();
 
@@ -389,7 +389,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringGMatch_PositionCaptures()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
         state.OpenTableLibrary();
 
@@ -412,7 +412,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringGMatch_NoMatches()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
         state.OpenTableLibrary();
 
@@ -430,7 +430,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringGMatch_SingleCharacter()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
         state.OpenTableLibrary();
 
@@ -451,7 +451,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringFind_And_GMatch_Consistency()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Test that find and gmatch work consistently with the same pattern
@@ -476,7 +476,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_Pattern_NegatedCharacterClassWithCapture()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Test the problematic pattern ^([^:]*):
@@ -514,7 +514,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringGSub_BasicReplacements()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Simple string replacement
@@ -539,7 +539,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringGSub_PatternReplacements()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Character class patterns
@@ -564,7 +564,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringGSub_FunctionReplacements()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Function replacement
@@ -602,7 +602,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringGSub_TableReplacements()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Table replacement
@@ -627,7 +627,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringGSub_EmptyPattern()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Empty pattern should match at every position
@@ -640,7 +640,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringGSub_BalancedPatterns()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Balanced parentheses pattern
@@ -663,7 +663,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringGSub_EscapeSequences()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Test %% escape (literal %)
@@ -676,7 +676,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringGSub_EdgeCases()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Empty string
@@ -701,7 +701,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_StringGSub_ComplexPatterns()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Email replacement
@@ -728,7 +728,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_PatternMatching_Consistency()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Test that all string functions work consistently with same patterns
@@ -766,7 +766,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_PatternMatching_SpecialPatterns()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Frontier pattern %f
@@ -791,7 +791,7 @@ public class PatternMatchingTests
     [Test]
     public void Test_PatternMatching_ErrorCases()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
 
         // Invalid pattern - missing closing bracket
@@ -813,7 +813,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_DollarSignPattern_EscapingIssue()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
         state.OpenTableLibrary();
 
@@ -855,7 +855,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_DollarSignPattern_CompleteExample()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
         state.OpenTableLibrary();
         state.OpenBasicLibrary();
@@ -902,7 +902,7 @@ public class PatternMatchingTests
     [Test]
     public async Task Test_DollarSignPattern_EdgeCases()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStringLibrary();
         state.OpenTableLibrary();
 

+ 2 - 2
tests/Lua.Tests/StringTests.cs

@@ -10,7 +10,7 @@ public class StringTests
     [TestCase("\r\n")]
     public async Task Test_ShortString_RealNewLine(string newLine)
     {
-        var result = await LuaState.Create().DoStringAsync($"return \"\\{newLine}\"");
+        var result = await LuaGlobalState.Create().DoStringAsync($"return \"\\{newLine}\"");
         Assert.That(result, Has.Length.EqualTo(1));
         Assert.That(result[0], Is.EqualTo(new LuaValue("\n")));
     }
@@ -18,7 +18,7 @@ public class StringTests
     [TestCase("fr-FR")]
     public async Task Test_StringFormat_Culture(string newLine)
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenBasicLibrary();
         state.OpenStringLibrary();
         var culture = CultureInfo.CurrentCulture;

+ 2 - 2
tests/Lua.Tests/ValidationTests.cs

@@ -8,7 +8,7 @@ public class ValidationTests
     [Test]
     public async Task Test_Simple()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStandardLibraries();
         LuaThreadAccess innerAccess = default!;
         state.Environment["wait"] = new LuaFunction("wait",
@@ -42,7 +42,7 @@ public class ValidationTests
     [Test]
     public async Task Test_Recursive()
     {
-        var state = LuaState.Create();
+        var state = LuaGlobalState.Create();
         state.OpenStandardLibraries();
         state.Environment["dostring"] = new LuaFunction("dostring",
             async (context, ct) => context.Return(await context.Access.DoStringAsync(context.GetArgument<string>(0), null, ct)));