Browse Source

Optimize: standard libraries

AnnulusGames 1 year ago
parent
commit
f8373017d7

+ 73 - 74
src/Lua/Standard/BasicLibrary.cs

@@ -4,66 +4,65 @@ using Lua.Runtime;
 
 namespace Lua.Standard;
 
-public static class BasicLibrary
+public sealed class BasicLibrary
 {
-    public static void OpenBasicLibrary(this LuaState state)
-    {
-        state.Environment["_G"] = state.Environment;
-        state.Environment["_VERSION"] = "Lua 5.2";
-        foreach (var func in Functions)
-        {
-            state.Environment[func.Name] = func;
-        }
-    }
+    public static readonly BasicLibrary Instance = new();
 
-    static readonly LuaFunction[] Functions = [
-        new("assert", Assert),
-        new("collectgarbage", CollectGarbage),
-        new("dofile", DoFile),
-        new("error", Error),
-        new("getmetatable", GetMetatable),
-        new("ipairs", IPairs),
-        new("loadfile", LoadFile),
-        new("load", Load),
-        new("next", Next),
-        new("pairs", Pairs),
-        new("pcall", PCall),
-        new("print", Print),
-        new("rawequal", RawEqual),
-        new("rawget", RawGet),
-        new("rawlen", RawLen),
-        new("rawset", RawSet),
-        new("select", Select),
-        new("setmetatable", SetMetatable),
-        new("tonumber", ToNumber),
-        new("tostring", ToString),
-        new("type", Type),
-        new("xpcall", XPCall),
-    ];
-
-    static readonly LuaFunction IPairsIterator = new("iterator", (context, buffer, cancellationToken) =>
+    public BasicLibrary()
     {
-        var table = context.GetArgument<LuaTable>(0);
-        var i = context.GetArgument<double>(1);
+        Functions = [
+            new("assert", Assert),
+            new("collectgarbage", CollectGarbage),
+            new("dofile", DoFile),
+            new("error", Error),
+            new("getmetatable", GetMetatable),
+            new("ipairs", IPairs),
+            new("loadfile", LoadFile),
+            new("load", Load),
+            new("next", Next),
+            new("pairs", Pairs),
+            new("pcall", PCall),
+            new("print", Print),
+            new("rawequal", RawEqual),
+            new("rawget", RawGet),
+            new("rawlen", RawLen),
+            new("rawset", RawSet),
+            new("select", Select),
+            new("setmetatable", SetMetatable),
+            new("tonumber", ToNumber),
+            new("tostring", ToString),
+            new("type", Type),
+            new("xpcall", XPCall),
+        ];
+
+        IPairsIterator = new("iterator", (context, buffer, cancellationToken) =>
+        {
+            var table = context.GetArgument<LuaTable>(0);
+            var i = context.GetArgument<double>(1);
+
+            i++;
+            if (table.TryGetValue(i, out var value))
+            {
+                buffer.Span[0] = i;
+                buffer.Span[1] = value;
+            }
+            else
+            {
+                buffer.Span[0] = LuaValue.Nil;
+                buffer.Span[1] = LuaValue.Nil;
+            }
 
-        i++;
-        if (table.TryGetValue(i, out var value))
-        {
-            buffer.Span[0] = i;
-            buffer.Span[1] = value;
-        }
-        else
-        {
-            buffer.Span[0] = LuaValue.Nil;
-            buffer.Span[1] = LuaValue.Nil;
-        }
+            return new(2);
+        });
 
-        return new(2);
-    });
+        PairsIterator = new("iterator", Next);
+    }
 
-    static readonly LuaFunction PairsIterator = new("iterator", Next);
+    public readonly LuaFunction[] Functions;
+    readonly LuaFunction IPairsIterator;
+    readonly LuaFunction PairsIterator;
 
-    public static ValueTask<int> Assert(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Assert(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument(0);
 
@@ -82,13 +81,13 @@ public static class BasicLibrary
         return new(context.ArgumentCount);
     }
 
-    public static ValueTask<int> CollectGarbage(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> CollectGarbage(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         GC.Collect();
         return new(0);
     }
 
-    public static async ValueTask<int> DoFile(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public async ValueTask<int> DoFile(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<string>(0);
 
@@ -100,7 +99,7 @@ public static class BasicLibrary
         return await new Closure(context.State, chunk).InvokeAsync(context, buffer, cancellationToken);
     }
 
-    public static ValueTask<int> Error(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Error(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var obj = context.ArgumentCount == 0 || context.Arguments[0].Type is LuaValueType.Nil
             ? "(error object is a nil value)"
@@ -109,7 +108,7 @@ public static class BasicLibrary
         throw new LuaRuntimeException(context.State.GetTraceback(), obj!);
     }
 
-    public static ValueTask<int> GetMetatable(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> GetMetatable(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument(0);
 
@@ -136,7 +135,7 @@ public static class BasicLibrary
         return new(1);
     }
 
-    public static ValueTask<int> IPairs(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> IPairs(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<LuaTable>(0);
 
@@ -157,7 +156,7 @@ public static class BasicLibrary
         return new(3);
     }
     
-    public static async ValueTask<int> LoadFile(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public async ValueTask<int> LoadFile(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         // Lua-CSharp does not support binary chunks, the mode argument is ignored.
         var arg0 = context.GetArgument<string>(0);
@@ -182,7 +181,7 @@ public static class BasicLibrary
         }
     }
 
-    public static ValueTask<int> Load(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Load(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         // Lua-CSharp does not support binary chunks, the mode argument is ignored.
         var arg0 = context.GetArgument(0);
@@ -223,7 +222,7 @@ public static class BasicLibrary
         }
     }
 
-    public static ValueTask<int> Next(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Next(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<LuaTable>(0);
         var arg1 = context.HasArgument(1) ? context.Arguments[1] : LuaValue.Nil;
@@ -241,7 +240,7 @@ public static class BasicLibrary
         }
     }
     
-    public static ValueTask<int> Pairs(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Pairs(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<LuaTable>(0);
 
@@ -262,7 +261,7 @@ public static class BasicLibrary
         return new(3);
     }
 
-    public static async ValueTask<int> PCall(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public async ValueTask<int> PCall(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<LuaFunction>(0);
 
@@ -290,7 +289,7 @@ public static class BasicLibrary
         }
     }
 
-    public static async ValueTask<int> Print(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public async ValueTask<int> Print(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         using var methodBuffer = new PooledArray<LuaValue>(1);
 
@@ -305,7 +304,7 @@ public static class BasicLibrary
         return 0;
     }
 
-    public static ValueTask<int> RawEqual(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> RawEqual(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument(0);
         var arg1 = context.GetArgument(1);
@@ -314,7 +313,7 @@ public static class BasicLibrary
         return new(1);
     }
 
-    public static ValueTask<int> RawGet(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> RawGet(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<LuaTable>(0);
         var arg1 = context.GetArgument(1);
@@ -323,7 +322,7 @@ public static class BasicLibrary
         return new(1);
     }
 
-    public static ValueTask<int> RawLen(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> RawLen(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument(0);
 
@@ -343,7 +342,7 @@ public static class BasicLibrary
         return new(1);
     }
 
-    public static ValueTask<int> RawSet(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> RawSet(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<LuaTable>(0);
         var arg1 = context.GetArgument(1);
@@ -353,7 +352,7 @@ public static class BasicLibrary
         return new(0);
     }
     
-    public static ValueTask<int> Select(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Select(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument(0);
 
@@ -391,7 +390,7 @@ public static class BasicLibrary
         }
     }
     
-    public static ValueTask<int> SetMetatable(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> SetMetatable(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<LuaTable>(0);
         var arg1 = context.GetArgument(1);
@@ -418,7 +417,7 @@ public static class BasicLibrary
         return new(1);
     }
 
-    public static ValueTask<int> ToNumber(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> ToNumber(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var e = context.GetArgument(0);
         int? toBase = context.HasArgument(1)
@@ -554,13 +553,13 @@ public static class BasicLibrary
         return value;
     }
 
-    public static ValueTask<int> ToString(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> ToString(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument(0);
         return arg0.CallToStringAsync(context, buffer, cancellationToken);
     }
     
-    public static ValueTask<int> Type(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Type(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument(0);
 
@@ -580,7 +579,7 @@ public static class BasicLibrary
         return new(1);
     }
 
-    public static async ValueTask<int> XPCall(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public async ValueTask<int> XPCall(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<LuaFunction>(0);
         var arg1 = context.GetArgument<LuaFunction>(1);

+ 32 - 37
src/Lua/Standard/BitwiseLibrary.cs

@@ -2,36 +2,31 @@ using Lua.Standard.Internal;
 
 namespace Lua.Standard;
 
-public static class BitwiseLibrary
+public sealed class BitwiseLibrary
 {
-    public static void OpenBitwiseLibrary(this LuaState state)
-    {
-        var bit32 = new LuaTable(0, Functions.Length);
-        foreach (var func in Functions)
-        {
-            bit32[func.Name] = func;
-        }
+    public static readonly BitwiseLibrary Instance = new();
 
-        state.Environment["bit32"] = bit32;
-        state.LoadedModules["bit32"] = bit32;
+    public BitwiseLibrary()
+    {
+        Functions = [
+            new("arshift", ArShift),
+            new("band", BAnd),
+            new("bnot", BNot),
+            new("bor", BOr),
+            new("btest", BTest),
+            new("bxor", BXor),
+            new("extract", Extract),
+            new("lrotate", LRotate),
+            new("lshift", LShift),
+            new("replace", Replace),
+            new("rrotate", RRotate),
+            new("rshift", RShift),
+        ];
     }
 
-    static readonly LuaFunction[] Functions = [
-        new ("arshift", ArShift),
-        new ("band", BAnd),
-        new ("bnot", BNot),
-        new ("bor", BOr),
-        new ("btest", BTest),
-        new ("bxor", BXor),
-        new ("extract", Extract),
-        new ("lrotate", LRotate),
-        new ("lshift", LShift),
-        new ("replace", Replace),
-        new ("rrotate", RRotate),
-        new ("rshift", RShift),
-    ];
-
-    public static ValueTask<int> ArShift(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public readonly LuaFunction[] Functions;
+
+    public ValueTask<int> ArShift(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var x = context.GetArgument<double>(0);
         var disp = context.GetArgument<double>(1);
@@ -55,7 +50,7 @@ public static class BitwiseLibrary
         return new(1);
     }
 
-    public static ValueTask<int> BAnd(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> BAnd(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         if (context.ArgumentCount == 0)
         {
@@ -81,7 +76,7 @@ public static class BitwiseLibrary
         return new(1);
     }
 
-    public static ValueTask<int> BNot(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> BNot(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, "bnot", 1, arg0);
@@ -91,7 +86,7 @@ public static class BitwiseLibrary
         return new(1);
     }
 
-    public static ValueTask<int> BOr(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> BOr(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         if (context.ArgumentCount == 0)
         {
@@ -117,7 +112,7 @@ public static class BitwiseLibrary
         return new(1);
     }
 
-    public static ValueTask<int> BTest(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> BTest(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         if (context.ArgumentCount == 0)
         {
@@ -143,7 +138,7 @@ public static class BitwiseLibrary
         return new(1);
     }
 
-    public static ValueTask<int> BXor(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> BXor(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         if (context.ArgumentCount == 0)
         {
@@ -169,7 +164,7 @@ public static class BitwiseLibrary
         return new(1);
     }
 
-    public static ValueTask<int> Extract(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Extract(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         var arg1 = context.GetArgument<double>(1);
@@ -200,7 +195,7 @@ public static class BitwiseLibrary
         return new(1);
     }
 
-    public static ValueTask<int> LRotate(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> LRotate(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var x = context.GetArgument<double>(0);
         var disp = context.GetArgument<double>(1);
@@ -224,7 +219,7 @@ public static class BitwiseLibrary
         return new(1);
     }
 
-    public static ValueTask<int> LShift(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> LShift(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var x = context.GetArgument<double>(0);
         var disp = context.GetArgument<double>(1);
@@ -252,7 +247,7 @@ public static class BitwiseLibrary
         return new(1);
     }
 
-    public static ValueTask<int> Replace(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Replace(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         var arg1 = context.GetArgument<double>(1);
@@ -288,7 +283,7 @@ public static class BitwiseLibrary
         return new(1);
     }
 
-    public static ValueTask<int> RRotate(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> RRotate(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var x = context.GetArgument<double>(0);
         var disp = context.GetArgument<double>(1);
@@ -312,7 +307,7 @@ public static class BitwiseLibrary
         return new(1);
     }
 
-    public static ValueTask<int> RShift(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> RShift(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var x = context.GetArgument<double>(0);
         var disp = context.GetArgument<double>(1);

+ 18 - 22
src/Lua/Standard/CoroutineLibrary.cs

@@ -1,47 +1,43 @@
 namespace Lua.Standard;
 
-public static class CoroutineLibrary
+public sealed class CoroutineLibrary
 {
-    public static void OpenCoroutineLibrary(this LuaState state)
-    {
-        var coroutine = new LuaTable(0, Functions.Length);
-        foreach (var func in Functions)
-        {
-            coroutine[func.Name] = func;
-        }
+    public static readonly CoroutineLibrary Instance = new();
 
-        state.Environment["coroutine"] = coroutine;
+    public CoroutineLibrary()
+    {
+        Functions = [
+            new("create", Create),
+            new("resume", Resume),
+            new("running", Running),
+            new("wrap", Wrap),
+            new("yield", Yield),
+        ];
     }
 
-    static readonly LuaFunction[] Functions = [
-        new("create", Create),
-        new("resume", Resume),
-        new("running", Running),
-        new("wrap", Wrap),
-        new("yield", Yield),
-    ];
+    public readonly LuaFunction[] Functions;
 
-    public static ValueTask<int> Create(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Create(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<LuaFunction>(0);
         buffer.Span[0] = new LuaCoroutine(arg0, true);
         return new(1);
     }
 
-    public static ValueTask<int> Resume(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Resume(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var thread = context.GetArgument<LuaThread>(0);
         return thread.ResumeAsync(context, buffer, cancellationToken);
     }
 
-    public static ValueTask<int> Running(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Running(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         buffer.Span[0] = context.Thread;
         buffer.Span[1] = context.Thread == context.State.MainThread;
         return new(2);
     }
 
-    public static ValueTask<int> Status(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Status(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var thread = context.GetArgument<LuaThread>(0);
         buffer.Span[0] = thread.GetStatus() switch
@@ -55,7 +51,7 @@ public static class CoroutineLibrary
         return new(1);
     }
 
-    public static ValueTask<int> Wrap(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Wrap(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<LuaFunction>(0);
         var thread = new LuaCoroutine(arg0, false);
@@ -81,7 +77,7 @@ public static class CoroutineLibrary
         return new(1);
     }
 
-    public static ValueTask<int> Yield(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Yield(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         return context.Thread.YieldAsync(context, buffer, cancellationToken);
     }

+ 26 - 35
src/Lua/Standard/IOLibrary.cs

@@ -3,37 +3,28 @@ using Lua.Standard.Internal;
 
 namespace Lua.Standard;
 
-public static class IOLibrary
+public sealed class IOLibrary
 {
-    public static void OpenIOLibrary(this LuaState state)
-    {
-        var io = new LuaTable(0, Functions.Length);
-        foreach (var func in Functions)
-        {
-            io[func.Name] = func;
-        }
+    public static readonly IOLibrary Instance = new();
 
-        io["stdio"] = new LuaValue(new FileHandle(Console.OpenStandardInput()));
-        io["stdout"] = new LuaValue(new FileHandle(Console.OpenStandardOutput()));
-        io["stderr"] = new LuaValue(new FileHandle(Console.OpenStandardError()));
-
-        state.Environment["io"] = io;
-        state.LoadedModules["io"] = io;
+    public IOLibrary()
+    {
+        Functions = [
+            new("close", Close),
+            new("flush", Flush),
+            new("input", Input),
+            new("lines", Lines),
+            new("open", Open),
+            new("output", Output),
+            new("read", Read),
+            new("type", Type),
+            new("write", Write),
+        ];
     }
 
-    static readonly LuaFunction[] Functions = [
-        new("close", Close),
-        new("flush", Flush),
-        new("input", Input),
-        new("lines", Lines),
-        new("open", Open),
-        new("output", Output),
-        new("read", Read),
-        new("type", Type),
-        new("write", Write),
-    ];
-
-    public static ValueTask<int> Close(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public readonly LuaFunction[] Functions;
+
+    public ValueTask<int> Close(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var file = context.HasArgument(0)
             ? context.GetArgument<FileHandle>(0)
@@ -54,7 +45,7 @@ public static class IOLibrary
         }
     }
 
-    public static ValueTask<int> Flush(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Flush(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var file = context.State.Environment["io"].Read<LuaTable>()["stdout"].Read<FileHandle>();
 
@@ -73,7 +64,7 @@ public static class IOLibrary
         }
     }
 
-    public static ValueTask<int> Input(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Input(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var io = context.State.Environment["io"].Read<LuaTable>();
 
@@ -100,7 +91,7 @@ public static class IOLibrary
         }
     }
 
-    public static ValueTask<int> Lines(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Lines(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         if (context.ArgumentCount == 0)
         {
@@ -140,7 +131,7 @@ public static class IOLibrary
         }
     }
 
-    public static ValueTask<int> Open(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Open(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var fileName = context.GetArgument<string>(0);
         var mode = context.HasArgument(1)
@@ -151,7 +142,7 @@ public static class IOLibrary
         return new(resultCount);
     }
 
-    public static ValueTask<int> Output(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Output(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var io = context.State.Environment["io"].Read<LuaTable>();
 
@@ -178,14 +169,14 @@ public static class IOLibrary
         }
     }
 
-    public static ValueTask<int> Read(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Read(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var file = context.State.Environment["io"].Read<LuaTable>()["stdio"].Read<FileHandle>();
         var resultCount = IOHelper.Read(context.State, file, "read", 0, context.Arguments, buffer, false);
         return new(resultCount);
     }
 
-    public static ValueTask<int> Type(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Type(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument(0);
 
@@ -201,7 +192,7 @@ public static class IOLibrary
         return new(1);
     }
 
-    public static ValueTask<int> Write(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Write(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var file = context.State.Environment["io"].Read<LuaTable>()["stdout"].Read<FileHandle>();
         var resultCount = IOHelper.Write(file, "write", context, buffer);

+ 64 - 75
src/Lua/Standard/MathematicsLibrary.cs

@@ -1,85 +1,74 @@
 namespace Lua.Standard;
 
-public static class MathematicsLibrary
+public sealed class MathematicsLibrary
 {
-    public static void OpenMathLibrary(this LuaState state)
-    {
-        state.Environment[RandomInstanceKey] = new(new RandomUserData(new Random()));
-
-        var math = new LuaTable(0, Functions.Length);
-        foreach (var func in Functions)
-        {
-            math[func.Name] = func;
-        }
-
-        math["pi"] = Math.PI;
-        math["huge"] = double.PositiveInfinity;
+    public static readonly MathematicsLibrary Instance = new();
+    public const string RandomInstanceKey = "__lua_mathematics_library_random_instance";
 
-        state.Environment["math"] = math;
-        state.LoadedModules["math"] = math;
+    public MathematicsLibrary()
+    {
+        Functions = [
+            new("abs", Abs),
+            new("acos", Acos),
+            new("asin", Asin),
+            new("atan2", Atan2),
+            new("atan", Atan),
+            new("ceil", Ceil),
+            new("cos", Cos),
+            new("cosh", Cosh),
+            new("deg", Deg),
+            new("exp", Exp),
+            new("floor", Floor),
+            new("fmod", Fmod),
+            new("frexp", Frexp),
+            new("ldexp", Ldexp),
+            new("log", Log),
+            new("max", Max),
+            new("min", Min),
+            new("modf", Modf),
+            new("pow", Pow),
+            new("rad", Rad),
+            new("random", Random),
+            new("randomseed", RandomSeed),
+            new("sin", Sin),
+            new("sinh", Sinh),
+            new("sqrt", Sqrt),
+            new("tan", Tan),
+            new("tanh", Tanh),
+        ];
     }
 
-    public const string RandomInstanceKey = "__lua_mathematics_library_random_instance";
+    public readonly LuaFunction[] Functions;
 
-    static readonly LuaFunction[] Functions = [
-        new("abs", Abs),
-        new("acos", Acos),
-        new("asin", Asin),
-        new("atan2", Atan2),
-        new("atan", Atan),
-        new("ceil", Ceil),
-        new("cos", Cos),
-        new("cosh", Cosh),
-        new("deg", Deg),
-        new("exp", Exp),
-        new("floor", Floor),
-        new("fmod", Fmod),
-        new("frexp", Frexp),
-        new("ldexp", Ldexp),
-        new("log", Log),
-        new("max", Max),
-        new("min", Min),
-        new("modf", Modf),
-        new("pow", Pow),
-        new("rad", Rad),
-        new("random", Random),
-        new("randomseed", RandomSeed),
-        new("sin", Sin),
-        new("sinh", Sinh),
-        new("sqrt", Sqrt),
-        new("tan", Tan),
-        new("tanh", Tanh),
-    ];
-
-    sealed class RandomUserData(Random random) : ILuaUserData
+    public sealed class RandomUserData(Random random) : ILuaUserData
     {
-        static LuaTable? SharedMetatable;
+        LuaTable? SharedMetatable;
         public LuaTable? Metatable { get => SharedMetatable; set => SharedMetatable = value; }
         public Random Random { get; } = random;
     }
 
-    public static ValueTask<int> Abs(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Abs(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         buffer.Span[0] = Math.Abs(arg0);
         return new(1);
     }
 
-    public static ValueTask<int> Acos(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Acos(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         buffer.Span[0] = Math.Acos(arg0);
         return new(1);
     }
 
-    public static ValueTask<int> Asin(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Asin(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         buffer.Span[0] = Math.Asin(arg0);
         return new(1);
     }
 
-    public static ValueTask<int> Atan2(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Atan2(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         var arg1 = context.GetArgument<double>(1);
@@ -88,56 +77,56 @@ public static class MathematicsLibrary
         return new(1);
     }
 
-    public static ValueTask<int> Atan(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Atan(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         buffer.Span[0] = Math.Atan(arg0);
         return new(1);
     }
 
-    public static ValueTask<int> Ceil(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Ceil(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         buffer.Span[0] = Math.Ceiling(arg0);
         return new(1);
     }
 
-    public static ValueTask<int> Cos(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Cos(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         buffer.Span[0] = Math.Cos(arg0);
         return new(1);
     }
 
-    public static ValueTask<int> Cosh(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Cosh(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         buffer.Span[0] = Math.Cosh(arg0);
         return new(1);
     }
 
-    public static ValueTask<int> Deg(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Deg(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         buffer.Span[0] = arg0 * (180.0 / Math.PI);
         return new(1);
     }
 
-    public static ValueTask<int> Exp(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Exp(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         buffer.Span[0] = Math.Exp(arg0);
         return new(1);
     }
 
-    public static ValueTask<int> Floor(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Floor(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         buffer.Span[0] = Math.Floor(arg0);
         return new(1);
     }
 
-    public static ValueTask<int> Fmod(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Fmod(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         var arg1 = context.GetArgument<double>(1);
@@ -145,7 +134,7 @@ public static class MathematicsLibrary
         return new(1);
     }
 
-    public static ValueTask<int> Frexp(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Frexp(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
 
@@ -155,7 +144,7 @@ public static class MathematicsLibrary
         return new(2);
     }
 
-    public static ValueTask<int> Ldexp(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Ldexp(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         var arg1 = context.GetArgument<double>(1);
@@ -164,7 +153,7 @@ public static class MathematicsLibrary
         return new(1);
     }
 
-    public static ValueTask<int> Log(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Log(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
 
@@ -181,7 +170,7 @@ public static class MathematicsLibrary
         return new(1);
     }
 
-    public static ValueTask<int> Max(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Max(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var x = context.GetArgument<double>(0);
         for (int i = 1; i < context.ArgumentCount; i++)
@@ -194,7 +183,7 @@ public static class MathematicsLibrary
         return new(1);
     }
 
-    public static ValueTask<int> Min(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Min(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var x = context.GetArgument<double>(0);
         for (int i = 1; i < context.ArgumentCount; i++)
@@ -207,7 +196,7 @@ public static class MathematicsLibrary
         return new(1);
     }
 
-    public static ValueTask<int> Modf(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Modf(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         var (i, f) = MathEx.Modf(arg0);
@@ -216,7 +205,7 @@ public static class MathematicsLibrary
         return new(2);
     }
 
-    public static ValueTask<int> Pow(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Pow(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         var arg1 = context.GetArgument<double>(1);
@@ -225,14 +214,14 @@ public static class MathematicsLibrary
         return new(1);
     }
 
-    public static ValueTask<int> Rad(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Rad(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         buffer.Span[0] = arg0 * (Math.PI / 180.0);
         return new(1);
     }
 
-    public static ValueTask<int> Random(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Random(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var rand = context.State.Environment[RandomInstanceKey].Read<RandomUserData>().Random;
 
@@ -255,42 +244,42 @@ public static class MathematicsLibrary
         return new(1);
     }
 
-    public static ValueTask<int> RandomSeed(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> RandomSeed(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         context.State.Environment[RandomInstanceKey] = new(new RandomUserData(new Random((int)BitConverter.DoubleToInt64Bits(arg0))));
         return new(0);
     }
 
-    public static ValueTask<int> Sin(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Sin(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         buffer.Span[0] = Math.Sin(arg0);
         return new(1);
     }
 
-    public static ValueTask<int> Sinh(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Sinh(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         buffer.Span[0] = Math.Sinh(arg0);
         return new(1);
     }
 
-    public static ValueTask<int> Sqrt(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Sqrt(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         buffer.Span[0] = Math.Sqrt(arg0);
         return new(1);
     }
 
-    public static ValueTask<int> Tan(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Tan(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         buffer.Span[0] = Math.Tan(arg0);
         return new(1);
     }
 
-    public static ValueTask<int> Tanh(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Tanh(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
         buffer.Span[0] = Math.Tanh(arg0);

+ 8 - 7
src/Lua/Standard/ModuleLibrary.cs

@@ -4,17 +4,18 @@ using Lua.Runtime;
 
 namespace Lua.Standard;
 
-public static class ModuleLibrary
+public sealed class ModuleLibrary
 {
-    public static void OpenModuleLibrary(this LuaState state)
+    public static readonly ModuleLibrary Instance = new();
+
+    public ModuleLibrary()
     {
-        var package = new LuaTable();
-        package["loaded"] = state.LoadedModules;
-        state.Environment["package"] = package;
-        state.Environment["require"] = new LuaFunction("require", Require);
+        RequireFunction = new("require", Require);
     }
 
-    public static async ValueTask<int> Require(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public readonly LuaFunction RequireFunction;
+
+    public async ValueTask<int> Require(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<string>(0);
         var loaded = context.State.LoadedModules;

+ 129 - 0
src/Lua/Standard/OpenLibsExtensions.cs

@@ -1,7 +1,136 @@
+using Lua.Runtime;
+
 namespace Lua.Standard;
 
 public static class OpenLibsExtensions
 {
+    public static void OpenBasicLibrary(this LuaState state)
+    {
+        state.Environment["_G"] = state.Environment;
+        state.Environment["_VERSION"] = "Lua 5.2";
+        foreach (var func in BasicLibrary.Instance.Functions)
+        {
+            state.Environment[func.Name] = func;
+        }
+    }
+
+    public static void OpenBitwiseLibrary(this LuaState state)
+    {
+        var bit32 = new LuaTable(0, BitwiseLibrary.Instance.Functions.Length);
+        foreach (var func in BitwiseLibrary.Instance.Functions)
+        {
+            bit32[func.Name] = func;
+        }
+
+        state.Environment["bit32"] = bit32;
+        state.LoadedModules["bit32"] = bit32;
+    }
+
+    public static void OpenCoroutineLibrary(this LuaState state)
+    {
+        var coroutine = new LuaTable(0, CoroutineLibrary.Instance.Functions.Length);
+        foreach (var func in CoroutineLibrary.Instance.Functions)
+        {
+            coroutine[func.Name] = func;
+        }
+
+        state.Environment["coroutine"] = coroutine;
+    }
+
+    public static void OpenIOLibrary(this LuaState state)
+    {
+        var io = new LuaTable(0, IOLibrary.Instance.Functions.Length);
+        foreach (var func in IOLibrary.Instance.Functions)
+        {
+            io[func.Name] = func;
+        }
+
+        io["stdio"] = new LuaValue(new FileHandle(Console.OpenStandardInput()));
+        io["stdout"] = new LuaValue(new FileHandle(Console.OpenStandardOutput()));
+        io["stderr"] = new LuaValue(new FileHandle(Console.OpenStandardError()));
+
+        state.Environment["io"] = io;
+        state.LoadedModules["io"] = io;
+    }
+
+    public static void OpenMathLibrary(this LuaState state)
+    {
+        state.Environment[MathematicsLibrary.RandomInstanceKey] = new(new MathematicsLibrary.RandomUserData(new Random()));
+
+        var math = new LuaTable(0, MathematicsLibrary.Instance.Functions.Length);
+        foreach (var func in MathematicsLibrary.Instance.Functions)
+        {
+            math[func.Name] = func;
+        }
+
+        math["pi"] = Math.PI;
+        math["huge"] = double.PositiveInfinity;
+
+        state.Environment["math"] = math;
+        state.LoadedModules["math"] = math;
+    }
+
+    public static void OpenModuleLibrary(this LuaState state)
+    {
+        var package = new LuaTable();
+        package["loaded"] = state.LoadedModules;
+        state.Environment["package"] = package;
+        state.Environment["require"] = ModuleLibrary.Instance.RequireFunction;
+    }
+
+    public static void OpenOperatingSystemLibrary(this LuaState state)
+    {
+        var os = new LuaTable(0, OperatingSystemLibrary.Instance.Functions.Length);
+        foreach (var func in OperatingSystemLibrary.Instance.Functions)
+        {
+            os[func.Name] = func;
+        }
+
+        state.Environment["os"] = os;
+        state.LoadedModules["os"] = os;
+    }
+
+    public static void OpenStringLibrary(this LuaState state)
+    {
+        var @string = new LuaTable(0, StringLibrary.Instance.Functions.Length);
+        foreach (var func in StringLibrary.Instance.Functions)
+        {
+            @string[func.Name] = func;
+        }
+
+        state.Environment["string"] = @string;
+        state.LoadedModules["string"] = @string;
+
+        // set __index
+        var key = new LuaValue("");
+        if (!state.TryGetMetatable(key, out var metatable))
+        {
+            metatable = new();
+            state.SetMetatable(key, metatable);
+        }
+
+        metatable[Metamethods.Index] = new LuaFunction("index", (context, buffer, cancellationToken) =>
+        {
+            context.GetArgument<string>(0);
+            var key = context.GetArgument(1);
+
+            buffer.Span[0] = @string[key];
+            return new(1);
+        });
+    }
+
+    public static void OpenTableLibrary(this LuaState state)
+    {
+        var table = new LuaTable(0, TableLibrary.Instance.Functions.Length);
+        foreach (var func in TableLibrary.Instance.Functions)
+        {
+            table[func.Name] = func;
+        }
+
+        state.Environment["table"] = table;
+        state.LoadedModules["table"] = table;
+    }
+
     public static void OpenStandardLibraries(this LuaState state)
     {
         state.OpenBasicLibrary();

+ 30 - 35
src/Lua/Standard/OperatingSystemLibrary.cs

@@ -3,41 +3,36 @@ using Lua.Standard.Internal;
 
 namespace Lua.Standard;
 
-public static class OperatingSystemLibrary
+public sealed class OperatingSystemLibrary
 {
-    public static void OpenOperatingSystemLibrary(this LuaState state)
-    {
-        var os = new LuaTable(0, Functions.Length);
-        foreach (var func in Functions)
-        {
-            os[func.Name] = func;
-        }
+    public static readonly OperatingSystemLibrary Instance = new();
 
-        state.Environment["os"] = os;
-        state.LoadedModules["os"] = os;
+    public OperatingSystemLibrary()
+    {
+        Functions = [
+            new("clock", Clock),
+            new("date", Date),
+            new("difftime", DiffTime),
+            new("execute", Execute),
+            new("exit", Exit),
+            new("getenv", GetEnv),
+            new("remove", Remove),
+            new("rename", Rename),
+            new("setlocale", SetLocale),
+            new("time", Time),
+            new("tmpname", TmpName),
+        ];
     }
 
-    static readonly LuaFunction[] Functions = [
-        new("clock", Clock),
-        new("date", Date),
-        new("difftime", DiffTime),
-        new("execute", Execute),
-        new("exit", Exit),
-        new("getenv", GetEnv),
-        new("remove", Remove),
-        new("rename", Rename),
-        new("setlocale", SetLocale),
-        new("time", Time),
-        new("tmpname", TmpName),
-    ];
-
-    public static ValueTask<int> Clock(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public readonly LuaFunction[] Functions;
+
+    public ValueTask<int> Clock(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         buffer.Span[0] = DateTimeHelper.GetUnixTime(DateTime.UtcNow, Process.GetCurrentProcess().StartTime);
         return new(1);
     }
 
-    public static ValueTask<int> Date(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Date(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var format = context.HasArgument(0)
             ? context.GetArgument<string>(0).AsSpan()
@@ -89,7 +84,7 @@ public static class OperatingSystemLibrary
         return new(1);
     }
 
-    public static ValueTask<int> DiffTime(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> DiffTime(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var t2 = context.GetArgument<double>(0);
         var t1 = context.GetArgument<double>(1);
@@ -97,7 +92,7 @@ public static class OperatingSystemLibrary
         return new(1);
     }
 
-    public static ValueTask<int> Execute(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Execute(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         // os.execute(command) is not supported
 
@@ -112,7 +107,7 @@ public static class OperatingSystemLibrary
         }
     }
 
-    public static ValueTask<int> Exit(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Exit(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         // Ignore 'close' parameter
 
@@ -146,14 +141,14 @@ public static class OperatingSystemLibrary
         return new(0);
     }
 
-    public static ValueTask<int> GetEnv(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> GetEnv(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var variable = context.GetArgument<string>(0);
         buffer.Span[0] = Environment.GetEnvironmentVariable(variable) ?? LuaValue.Nil;
         return new(1);
     }
 
-    public static ValueTask<int> Remove(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Remove(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var fileName = context.GetArgument<string>(0);
         try
@@ -171,7 +166,7 @@ public static class OperatingSystemLibrary
         }
     }
 
-    public static ValueTask<int> Rename(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Rename(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var oldName = context.GetArgument<string>(0);
         var newName = context.GetArgument<string>(1);
@@ -190,7 +185,7 @@ public static class OperatingSystemLibrary
         }
     }
 
-    public static ValueTask<int> SetLocale(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> SetLocale(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         // os.setlocale is not supported (always return nil)
 
@@ -198,7 +193,7 @@ public static class OperatingSystemLibrary
         return new(1);
     }
 
-    public static ValueTask<int> Time(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Time(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         if (context.HasArgument(0))
         {
@@ -214,7 +209,7 @@ public static class OperatingSystemLibrary
         }
     }
 
-    public static ValueTask<int> TmpName(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> TmpName(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         buffer.Span[0] = Path.GetTempFileName();
         return new(1);

+ 34 - 57
src/Lua/Standard/StringLibrary.cs

@@ -1,57 +1,34 @@
 using System.Text;
 using Lua.Internal;
-using Lua.Runtime;
 
 namespace Lua.Standard;
 
-public static class StringLibrary
+public sealed class StringLibrary
 {
-    public static void OpenStringLibrary(this LuaState state)
-    {
-        var @string = new LuaTable(0, Functions.Length);
-        foreach (var func in Functions)
-        {
-            @string[func.Name] = func;
-        }
-
-        state.Environment["string"] = @string;
-        state.LoadedModules["string"] = @string;
-
-        // set __index
-        var key = new LuaValue("");
-        if (!state.TryGetMetatable(key, out var metatable))
-        {
-            metatable = new();
-            state.SetMetatable(key, metatable);
-        }
+    public static readonly StringLibrary Instance = new();
 
-        metatable[Metamethods.Index] = new LuaFunction("index", (context, buffer, cancellationToken) =>
-        {
-            context.GetArgument<string>(0);
-            var key = context.GetArgument(1);
-
-            buffer.Span[0] = @string[key];
-            return new(1);
-        });
+    public StringLibrary()
+    {
+        Functions = [
+            new("byte", Byte),
+            new("char", Char),
+            new("dump", Dump),
+            new("find", Find),
+            new("format", Format),
+            new("gmatch", GMatch),
+            new("gsub", GSub),
+            new("len", Len),
+            new("lower", Lower),
+            new("rep", Rep),
+            new("reverse", Reverse),
+            new("sub", Sub),
+            new("upper", Upper),
+        ];
     }
 
-    static readonly LuaFunction[] Functions = [
-        new("byte", Byte),
-        new("char", Char),
-        new("dump", Dump),
-        new("find", Find),
-        new("format", Format),
-        new("gmatch", GMatch),
-        new("gsub", GSub),
-        new("len", Len),
-        new("lower", Lower),
-        new("rep", Rep),
-        new("reverse", Reverse),
-        new("sub", Sub),
-        new("upper", Upper),
-    ];
-
-    public static ValueTask<int> Byte(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public readonly LuaFunction[] Functions;
+
+    public ValueTask<int> Byte(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var s = context.GetArgument<string>(0);
         var i = context.HasArgument(1)
@@ -73,7 +50,7 @@ public static class StringLibrary
         return new(span.Length);
     }
 
-    public static ValueTask<int> Char(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Char(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         if (context.ArgumentCount == 0)
         {
@@ -93,13 +70,13 @@ public static class StringLibrary
         return new(1);
     }
 
-    public static ValueTask<int> Dump(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Dump(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         // stirng.dump is not supported (throw exception)
         throw new NotSupportedException("stirng.dump is not supported");
     }
 
-    public static ValueTask<int> Find(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Find(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var s = context.GetArgument<string>(0);
         var pattern = context.GetArgument<string>(1);
@@ -169,7 +146,7 @@ public static class StringLibrary
         }
     }
 
-    public static async ValueTask<int> Format(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public async ValueTask<int> Format(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var format = context.GetArgument<string>(0);
 
@@ -445,7 +422,7 @@ public static class StringLibrary
         return 1;
     }
 
-    public static ValueTask<int> GMatch(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> GMatch(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var s = context.GetArgument<string>(0);
         var pattern = context.GetArgument<string>(1);
@@ -487,7 +464,7 @@ public static class StringLibrary
         return new(1);
     }
 
-    public static async ValueTask<int> GSub(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public async ValueTask<int> GSub(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var s = context.GetArgument<string>(0);
         var pattern = context.GetArgument<string>(1);
@@ -580,21 +557,21 @@ public static class StringLibrary
         return 1;
     }
 
-    public static ValueTask<int> Len(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Len(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var s = context.GetArgument<string>(0);
         buffer.Span[0] = s.Length;
         return new(1);
     }
 
-    public static ValueTask<int> Lower(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Lower(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var s = context.GetArgument<string>(0);
         buffer.Span[0] = s.ToLower();
         return new(1);
     }
 
-    public static ValueTask<int> Rep(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Rep(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var s = context.GetArgument<string>(0);
         var n_arg = context.GetArgument<double>(1);
@@ -620,7 +597,7 @@ public static class StringLibrary
         return new(1);
     }
 
-    public static ValueTask<int> Reverse(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Reverse(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var s = context.GetArgument<string>(0);
         using var strBuffer = new PooledArray<char>(s.Length);
@@ -631,7 +608,7 @@ public static class StringLibrary
         return new(1);
     }
 
-    public static ValueTask<int> Sub(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Sub(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var s = context.GetArgument<string>(0);
         var i = context.GetArgument<double>(1);
@@ -646,7 +623,7 @@ public static class StringLibrary
         return new(1);
     }
 
-    public static ValueTask<int> Upper(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Upper(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var s = context.GetArgument<string>(0);
         buffer.Span[0] = s.ToUpper();

+ 22 - 27
src/Lua/Standard/TableLibrary.cs

@@ -5,28 +5,23 @@ using Lua.Runtime;
 
 namespace Lua.Standard;
 
-public static class TableLibrary
+public sealed class TableLibrary
 {
-    public static void OpenTableLibrary(this LuaState state)
-    {
-        var table = new LuaTable(0, Functions.Length);
-        foreach (var func in Functions)
-        {
-            table[func.Name] = func;
-        }
+    public static readonly TableLibrary Instance = new();
 
-        state.Environment["table"] = table;
-        state.LoadedModules["table"] = table;
+    public TableLibrary()
+    {
+        Functions = [
+            new("concat", Concat),
+            new("insert", Insert),
+            new("pack", Pack),
+            new("remove", Remove),
+            new("sort", Sort),
+            new("unpack", Unpack),
+        ];
     }
 
-    static readonly LuaFunction[] Functions = [
-        new("concat", Concat),
-        new("insert", Insert),
-        new("pack", Pack),
-        new("remove", Remove),
-        new("sort", Sort),
-        new("unpack", Unpack),
-    ];
+    public readonly LuaFunction[] Functions;
 
     // TODO: optimize
     static readonly Chunk defaultComparer = new()
@@ -47,7 +42,7 @@ public static class TableLibrary
         UpValues = [],
     };
 
-    public static ValueTask<int> Concat(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Concat(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<LuaTable>(0);
         var arg1 = context.HasArgument(1)
@@ -86,7 +81,7 @@ public static class TableLibrary
         return new(1);
     }
 
-    public static ValueTask<int> Insert(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Insert(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var table = context.GetArgument<LuaTable>(0);
 
@@ -111,7 +106,7 @@ public static class TableLibrary
         return new(0);
     }
 
-    public static ValueTask<int> Pack(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Pack(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var table = new LuaTable(context.ArgumentCount, 1);
 
@@ -126,7 +121,7 @@ public static class TableLibrary
         return new(1);
     }
 
-    public static ValueTask<int> Remove(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Remove(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var table = context.GetArgument<LuaTable>(0);
         var n_arg = context.HasArgument(1)
@@ -157,7 +152,7 @@ public static class TableLibrary
         return new(1);
     }
 
-    public static async ValueTask<int> Sort(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public async ValueTask<int> Sort(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<LuaTable>(0);
         var arg1 = context.HasArgument(1)
@@ -168,7 +163,7 @@ public static class TableLibrary
         return 0;
     }
 
-    static async ValueTask QuickSortAsync(LuaFunctionExecutionContext context, Memory<LuaValue> memory, int low, int high, LuaFunction comparer, CancellationToken cancellationToken)
+    async ValueTask QuickSortAsync(LuaFunctionExecutionContext context, Memory<LuaValue> memory, int low, int high, LuaFunction comparer, CancellationToken cancellationToken)
     {
         if (low < high)
         {
@@ -178,7 +173,7 @@ public static class TableLibrary
         }
     }
 
-    static async ValueTask<int> PartitionAsync(LuaFunctionExecutionContext context, Memory<LuaValue> memory, int low, int high, LuaFunction comparer, CancellationToken cancellationToken)
+    async ValueTask<int> PartitionAsync(LuaFunctionExecutionContext context, Memory<LuaValue> memory, int low, int high, LuaFunction comparer, CancellationToken cancellationToken)
     {
         using var methodBuffer = new PooledArray<LuaValue>(1);
 
@@ -207,12 +202,12 @@ public static class TableLibrary
     }
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    static void Swap(Span<LuaValue> span, int i, int j)
+    void Swap(Span<LuaValue> span, int i, int j)
     {
         (span[i], span[j]) = (span[j], span[i]);
     }
 
-    public static ValueTask<int> Unpack(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    public ValueTask<int> Unpack(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<LuaTable>(0);
         var arg1 = context.HasArgument(1)