| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- using System.Runtime.CompilerServices;
- using System.Runtime.InteropServices;
- using Lua.Runtime;
- namespace Lua;
- [StructLayout(LayoutKind.Auto)]
- public readonly record struct LuaFunctionExecutionContext
- {
- public LuaState State => Thread.State;
- public required LuaThreadAccess Access { get; init; }
- public LuaThread Thread => Access.Thread;
- public required int ArgumentCount { get; init; }
- public int FrameBase => Thread.Stack.Count - ArgumentCount;
- public required int ReturnFrameBase { get; init; }
- //public object? AdditionalContext { get; init; }
- public ReadOnlySpan<LuaValue> Arguments
- {
- get
- {
- var stack = Thread.Stack.AsSpan();
- return stack.Slice(stack.Length - ArgumentCount);
- }
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool HasArgument(int index)
- {
- return ArgumentCount > index && Arguments[index].Type is not LuaValueType.Nil;
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public LuaValue GetArgument(int index)
- {
- ThrowIfArgumentNotExists(index);
- return Arguments[index];
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal LuaValue GetArgumentOrDefault(int index, LuaValue defaultValue = default)
- {
- if (ArgumentCount <= index)
- {
- return defaultValue;
- }
- return Arguments[index];
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public T GetArgument<T>(int index)
- {
- ThrowIfArgumentNotExists(index);
- var arg = Arguments[index];
- if (!arg.TryRead<T>(out var argValue))
- {
- var t = typeof(T);
- if ((t == typeof(int) || t == typeof(long)) && arg.TryReadNumber(out _))
- {
- LuaRuntimeException.BadArgumentNumberIsNotInteger(Thread, index + 1);
- }
- else if (LuaValue.TryGetLuaValueType(t, out var type))
- {
- LuaRuntimeException.BadArgument(Thread, 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");
- }
- else
- {
- LuaRuntimeException.BadArgument(Thread, index + 1, t.Name, arg.TypeToString());
- }
- }
- return argValue;
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal T GetArgumentOrDefault<T>(int index, T defaultValue = default!)
- {
- if (ArgumentCount <= index)
- {
- return defaultValue;
- }
- var arg = Arguments[index];
- if (arg.Type is LuaValueType.Nil)
- {
- return defaultValue;
- }
- if (!arg.TryRead<T>(out var argValue))
- {
- var t = typeof(T);
- if ((t == typeof(int) || t == typeof(long)) && arg.TryReadNumber(out _))
- {
- LuaRuntimeException.BadArgumentNumberIsNotInteger(Thread, index + 1);
- }
- else if (LuaValue.TryGetLuaValueType(t, out var type))
- {
- LuaRuntimeException.BadArgument(Thread, 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");
- }
- else
- {
- LuaRuntimeException.BadArgument(Thread, index + 1, t.Name, arg.TypeToString());
- }
- }
- return argValue;
- }
- public int Return()
- {
- Thread.Stack.PopUntil(ReturnFrameBase);
- return 0;
- }
- public int Return(LuaValue result)
- {
- var stack = Thread.Stack;
- stack.SetTop(ReturnFrameBase + 1);
- stack.FastGet(ReturnFrameBase) = result;
- return 1;
- }
- public int Return(LuaValue result0, LuaValue result1)
- {
- var stack = Thread.Stack;
- stack.SetTop(ReturnFrameBase + 2);
- stack.FastGet(ReturnFrameBase) = result0;
- stack.FastGet(ReturnFrameBase + 1) = result1;
- return 2;
- }
- public int Return(LuaValue result0, LuaValue result1, LuaValue result2)
- {
- var stack = Thread.Stack;
- stack.SetTop(ReturnFrameBase + 3);
- stack.FastGet(ReturnFrameBase) = result0;
- stack.FastGet(ReturnFrameBase + 1) = result1;
- stack.FastGet(ReturnFrameBase + 2) = result2;
- return 3;
- }
- public int Return(ReadOnlySpan<LuaValue> results)
- {
- var stack = Thread.Stack;
- stack.EnsureCapacity(ReturnFrameBase + results.Length);
- results.CopyTo(stack.GetBuffer()[ReturnFrameBase..(ReturnFrameBase + results.Length)]);
- stack.SetTop(ReturnFrameBase + results.Length);
- return results.Length;
- }
- internal int Return(LuaValue result0, ReadOnlySpan<LuaValue> results)
- {
- var stack = Thread.Stack;
- stack.EnsureCapacity(ReturnFrameBase + results.Length);
- stack.SetTop(ReturnFrameBase + results.Length + 1);
- var buffer = stack.GetBuffer();
- buffer[ReturnFrameBase] = result0;
- results.CopyTo(buffer[(ReturnFrameBase + 1)..(ReturnFrameBase + results.Length + 1)]);
- return results.Length + 1;
- }
- public Span<LuaValue> GetReturnBuffer(int count)
- {
- var stack = Thread.Stack;
- stack.SetTop(ReturnFrameBase + count);
- var buffer = stack.GetBuffer()[ReturnFrameBase..(ReturnFrameBase + count)];
- return buffer;
- }
- public CSharpClosure? GetCsClosure()
- {
- return Thread.GetCurrentFrame().Function as CSharpClosure;
- }
- internal void ThrowBadArgument(int index, string message)
- {
- LuaRuntimeException.BadArgument(Thread, index, Thread.GetCurrentFrame().Function.Name, message);
- }
- void ThrowIfArgumentNotExists(int index)
- {
- if (ArgumentCount <= index)
- {
- LuaRuntimeException.BadArgument(Thread, index + 1, Thread.GetCurrentFrame().Function.Name);
- }
- }
- }
|