using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using Lua.Internal; using Lua.Platforms; using Lua.Runtime; using Lua.Standard; namespace Lua; sealed class LuaGlobalState { // states readonly LuaState mainState; FastStackCore stateStack; readonly LuaTable environment; readonly LuaTable registry = new(); readonly UpValue envUpValue; FastStackCore debugBufferPool; public LuaPlatform Platform { get; set; } public ILuaModuleLoader? ModuleLoader { get; set; } internal UpValue EnvUpValue => envUpValue; internal ref FastStackCore ThreadStack => ref stateStack; internal ref FastStackCore DebugBufferPool => ref debugBufferPool; public LuaTable Environment => environment; public LuaTable Registry => registry; public LuaTable LoadedModules => registry[ModuleLibrary.LoadedKeyForRegistry].Read(); public LuaTable PreloadModules => registry[ModuleLibrary.PreloadKeyForRegistry].Read(); public LuaState MainThread => mainState; // metatables LuaTable? nilMetatable; LuaTable? numberMetatable; LuaTable? stringMetatable; LuaTable? booleanMetatable; LuaTable? functionMetatable; LuaTable? stateMetatable; 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 => stateMetatable, LuaValueType.UserData => value.UnsafeRead().Metatable, LuaValueType.Table => value.UnsafeRead().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: stateMetatable = metatable; break; case LuaValueType.UserData: value.UnsafeRead().Metatable = metatable; break; case LuaValueType.Table: value.UnsafeRead().Metatable = metatable; break; } } }