LuaFunctionExecutionContext.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. using System.Runtime.CompilerServices;
  2. using System.Runtime.InteropServices;
  3. using Lua.CodeAnalysis;
  4. namespace Lua;
  5. [StructLayout(LayoutKind.Auto)]
  6. public readonly record struct LuaFunctionExecutionContext
  7. {
  8. public required LuaState State { get; init; }
  9. public required LuaThread Thread { get; init; }
  10. public required int ArgumentCount { get; init; }
  11. public required int FrameBase { get; init; }
  12. public SourcePosition? SourcePosition { get; init; }
  13. public string? RootChunkName { get; init; }
  14. public string? ChunkName { get; init; }
  15. public int? CallerInstructionIndex { get; init; }
  16. public object? AdditionalContext { get; init; }
  17. public ReadOnlySpan<LuaValue> Arguments
  18. {
  19. get
  20. {
  21. return Thread.GetStackValues().Slice(FrameBase, ArgumentCount);
  22. }
  23. }
  24. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  25. public bool HasArgument(int index)
  26. {
  27. return ArgumentCount > index && Arguments[index].Type is not LuaValueType.Nil;
  28. }
  29. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  30. public LuaValue GetArgument(int index)
  31. {
  32. ThrowIfArgumentNotExists(index);
  33. return Arguments[index];
  34. }
  35. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  36. internal LuaValue GetArgumentOrDefault(int index, LuaValue defaultValue = default)
  37. {
  38. if (ArgumentCount <= index)
  39. {
  40. return defaultValue;
  41. }
  42. return Arguments[index];
  43. }
  44. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  45. public T GetArgument<T>(int index)
  46. {
  47. ThrowIfArgumentNotExists(index);
  48. var arg = Arguments[index];
  49. if (!arg.TryRead<T>(out var argValue))
  50. {
  51. var t = typeof(T);
  52. if ((t == typeof(int) || t == typeof(long)) && arg.TryReadNumber(out _))
  53. {
  54. LuaRuntimeException.BadArgumentNumberIsNotInteger(State.GetTraceback(), index + 1, Thread.GetCurrentFrame().Function.Name);
  55. }
  56. else if (LuaValue.TryGetLuaValueType(t, out var type))
  57. {
  58. LuaRuntimeException.BadArgument(State.GetTraceback(), index + 1, Thread.GetCurrentFrame().Function.Name, type.ToString(), arg.Type.ToString());
  59. }
  60. else if(arg.Type is LuaValueType.UserData or LuaValueType.LightUserData)
  61. {
  62. LuaRuntimeException.BadArgument(State.GetTraceback(), index + 1, Thread.GetCurrentFrame().Function.Name, t.Name, arg.UnsafeRead<object>()?.GetType().ToString()??"userdata: 0");
  63. }
  64. else
  65. {
  66. LuaRuntimeException.BadArgument(State.GetTraceback(), index + 1, Thread.GetCurrentFrame().Function.Name, t.Name, arg.Type.ToString());
  67. }
  68. }
  69. return argValue;
  70. }
  71. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  72. internal T GetArgumentOrDefault<T>(int index,T defaultValue =default!)
  73. {
  74. if (ArgumentCount <= index)
  75. {
  76. return defaultValue;
  77. }
  78. var arg = Arguments[index];
  79. if(arg.Type is LuaValueType.Nil)
  80. {
  81. return defaultValue;
  82. }
  83. if (!arg.TryRead<T>(out var argValue))
  84. {
  85. var t = typeof(T);
  86. if ((t == typeof(int) || t == typeof(long)) && arg.TryReadNumber(out _))
  87. {
  88. LuaRuntimeException.BadArgumentNumberIsNotInteger(State.GetTraceback(), index + 1, Thread.GetCurrentFrame().Function.Name);
  89. }
  90. else if (LuaValue.TryGetLuaValueType(t, out var type))
  91. {
  92. LuaRuntimeException.BadArgument(State.GetTraceback(), index + 1, Thread.GetCurrentFrame().Function.Name, type.ToString(), arg.Type.ToString());
  93. }
  94. else if(arg.Type is LuaValueType.UserData or LuaValueType.LightUserData)
  95. {
  96. LuaRuntimeException.BadArgument(State.GetTraceback(), index + 1, Thread.GetCurrentFrame().Function.Name, t.Name, arg.UnsafeRead<object>()?.GetType().ToString()??"userdata: 0");
  97. }
  98. else
  99. {
  100. LuaRuntimeException.BadArgument(State.GetTraceback(), index + 1, Thread.GetCurrentFrame().Function.Name, t.Name, arg.Type.ToString());
  101. }
  102. }
  103. return argValue;
  104. }
  105. internal void ThrowBadArgument(int index, string message)
  106. {
  107. LuaRuntimeException.BadArgument(State.GetTraceback(), index, Thread.GetCurrentFrame().Function.Name, message);
  108. }
  109. void ThrowIfArgumentNotExists(int index)
  110. {
  111. if (ArgumentCount <= index)
  112. {
  113. LuaRuntimeException.BadArgument(State.GetTraceback(), index + 1, Thread.GetCurrentFrame().Function.Name);
  114. }
  115. }
  116. }