ScriptExecutionContext.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using MoonSharp.Interpreter.Execution.VM;
  6. using MoonSharp.Interpreter.Interop.LuaStateInterop;
  7. namespace MoonSharp.Interpreter.Execution
  8. {
  9. /// <summary>
  10. /// Class giving access to details of the environment where the script is executing
  11. /// </summary>
  12. public class ScriptExecutionContext
  13. {
  14. Processor m_Processor;
  15. CallbackFunction m_Callback;
  16. internal ScriptExecutionContext(Processor p, CallbackFunction callBackFunction)
  17. {
  18. m_Processor = p;
  19. m_Callback = callBackFunction;
  20. }
  21. /// <summary>
  22. /// Gets or sets the additional data associated to this CLR function call.
  23. /// </summary>
  24. public object AdditionalData
  25. {
  26. get { return m_Callback.AdditionalData; }
  27. set { m_Callback.AdditionalData = value; }
  28. }
  29. /// <summary>
  30. /// Gets the metatable associated with the given value.
  31. /// </summary>
  32. /// <param name="value">The value.</param>
  33. /// <returns></returns>
  34. public Table GetMetatable(DynValue value)
  35. {
  36. return m_Processor.GetMetatable(value);
  37. }
  38. /// <summary>
  39. /// Gets the specified metamethod associated with the given value.
  40. /// </summary>
  41. /// <param name="value">The value.</param>
  42. /// <param name="metamethod">The metamethod name.</param>
  43. /// <returns></returns>
  44. public DynValue GetMetamethod(DynValue value, string metamethod)
  45. {
  46. return m_Processor.GetMetamethod(value, metamethod);
  47. }
  48. /// <summary>
  49. /// prepares a tail call request for the specified metamethod, or null if no metamethod is found.
  50. /// </summary>
  51. public DynValue GetMetamethodTailCall(DynValue value, string metamethod, params DynValue[] args)
  52. {
  53. DynValue meta = this.GetMetamethod(value, metamethod);
  54. if (meta == null) return null;
  55. return DynValue.NewTailCallReq(meta, args);
  56. }
  57. /// <summary>
  58. /// Gets the metamethod to be used for a binary operation using op1 and op2.
  59. /// </summary>
  60. public DynValue GetBinaryMetamethod(DynValue op1, DynValue op2, string eventName)
  61. {
  62. return m_Processor.GetBinaryMetamethod(op1, op2, eventName);
  63. }
  64. /// <summary>
  65. /// Gets the script object associated with this request
  66. /// </summary>
  67. /// <returns></returns>
  68. public Script GetScript()
  69. {
  70. return m_Processor.GetScript();
  71. }
  72. /// <summary>
  73. /// Gets the coroutine which is performing the call
  74. /// </summary>
  75. public Coroutine GetCallingCoroutine()
  76. {
  77. return m_Processor.AssociatedCoroutine;
  78. }
  79. /// <summary>
  80. /// Calls a callback function implemented in "classic way".
  81. /// Useful to port C code from Lua, or C# code from UniLua and KopiLua.
  82. /// Lua : http://www.lua.org/
  83. /// UniLua : http://github.com/xebecnan/UniLua
  84. /// KopiLua : http://github.com/NLua/KopiLua
  85. /// </summary>
  86. /// <param name="args">The arguments.</param>
  87. /// <param name="functionName">Name of the function - for error messages.</param>
  88. /// <param name="callback">The callback.</param>
  89. /// <returns></returns>
  90. public DynValue EmulateClassicCall(CallbackArguments args, string functionName, Func<LuaState, int> callback)
  91. {
  92. LuaState L = new LuaState(this, args, functionName);
  93. int retvals = callback(L);
  94. return L.GetReturnValue(retvals);
  95. }
  96. /// <summary>
  97. /// Calls the specified function, supporting most cases. The called function must not yield.
  98. /// </summary>
  99. /// <param name="func">The function; it must be a Function or ClrFunction or have a call metamethod defined.</param>
  100. /// <param name="args">The arguments.</param>
  101. /// <returns></returns>
  102. /// <exception cref="System.ScriptRuntimeException">If the function yields, returns a tail call request with continuations/handlers or, of course, if it encounters errors.</exception>
  103. public DynValue Call(DynValue func, params DynValue[] args)
  104. {
  105. if (func.Type == DataType.Function)
  106. {
  107. return this.GetScript().Call(func, args);
  108. }
  109. else if (func.Type == DataType.ClrFunction)
  110. {
  111. while (true)
  112. {
  113. DynValue ret = func.Callback.Invoke(this, args, false);
  114. if (ret.Type == DataType.YieldRequest)
  115. {
  116. throw ScriptRuntimeException.CannotYield();
  117. }
  118. else if (ret.Type == DataType.TailCallRequest)
  119. {
  120. var tail = ret.TailCallData;
  121. if (tail.Continuation != null || tail.ErrorHandler != null)
  122. {
  123. throw new ScriptRuntimeException("the function passed cannot be called directly. wrap in a script function instead.");
  124. }
  125. else
  126. {
  127. args = tail.Args;
  128. func = tail.Function;
  129. }
  130. }
  131. else
  132. {
  133. return ret;
  134. }
  135. }
  136. }
  137. else
  138. {
  139. int maxloops = 10;
  140. while (maxloops > 0)
  141. {
  142. DynValue v = this.GetMetamethod(func, "__call");
  143. if (v == null && v.IsNil())
  144. {
  145. throw ScriptRuntimeException.AttemptToCallNonFunc(func.Type);
  146. }
  147. func = v;
  148. if (func.Type == DataType.Function || func.Type == DataType.ClrFunction)
  149. {
  150. return Call(func, args);
  151. }
  152. }
  153. throw ScriptRuntimeException.LoopInCall();
  154. }
  155. }
  156. }
  157. }