using System; using System.Collections.Generic; using System.Linq; using System.Text; using MoonSharp.Interpreter.Execution.VM; using MoonSharp.Interpreter.Interop.LuaStateInterop; namespace MoonSharp.Interpreter.Execution { /// /// Class giving access to details of the environment where the script is executing /// public class ScriptExecutionContext { Processor m_Processor; CallbackFunction m_Callback; internal ScriptExecutionContext(Processor p, CallbackFunction callBackFunction) { m_Processor = p; m_Callback = callBackFunction; } /// /// Gets or sets the additional data associated to this CLR function call. /// public object AdditionalData { get { return m_Callback.AdditionalData; } set { m_Callback.AdditionalData = value; } } /// /// Gets the metatable associated with the given value. /// /// The value. /// public Table GetMetatable(DynValue value) { return m_Processor.GetMetatable(value); } /// /// Gets the specified metamethod associated with the given value. /// /// The value. /// The metamethod name. /// public DynValue GetMetamethod(DynValue value, string metamethod) { return m_Processor.GetMetamethod(value, metamethod); } /// /// prepares a tail call request for the specified metamethod, or null if no metamethod is found. /// public DynValue GetMetamethodTailCall(DynValue value, string metamethod, params DynValue[] args) { DynValue meta = this.GetMetamethod(value, metamethod); if (meta == null) return null; return DynValue.NewTailCallReq(meta, args); } /// /// Gets the metamethod to be used for a binary operation using op1 and op2. /// public DynValue GetBinaryMetamethod(DynValue op1, DynValue op2, string eventName) { return m_Processor.GetBinaryMetamethod(op1, op2, eventName); } /// /// Gets the script object associated with this request /// /// public Script GetScript() { return m_Processor.GetScript(); } /// /// Gets the coroutine which is performing the call /// public Coroutine GetCallingCoroutine() { return m_Processor.AssociatedCoroutine; } /// /// Calls a callback function implemented in "classic way". /// Useful to port C code from Lua, or C# code from UniLua and KopiLua. /// Lua : http://www.lua.org/ /// UniLua : http://github.com/xebecnan/UniLua /// KopiLua : http://github.com/NLua/KopiLua /// /// The arguments. /// Name of the function - for error messages. /// The callback. /// public DynValue EmulateClassicCall(CallbackArguments args, string functionName, Func callback) { LuaState L = new LuaState(this, args, functionName); int retvals = callback(L); return L.GetReturnValue(retvals); } /// /// Calls the specified function, supporting most cases. The called function must not yield. /// /// The function; it must be a Function or ClrFunction or have a call metamethod defined. /// The arguments. /// /// If the function yields, returns a tail call request with continuations/handlers or, of course, if it encounters errors. public DynValue Call(DynValue func, params DynValue[] args) { if (func.Type == DataType.Function) { return this.GetScript().Call(func, args); } else if (func.Type == DataType.ClrFunction) { while (true) { DynValue ret = func.Callback.Invoke(this, args, false); if (ret.Type == DataType.YieldRequest) { throw ScriptRuntimeException.CannotYield(); } else if (ret.Type == DataType.TailCallRequest) { var tail = ret.TailCallData; if (tail.Continuation != null || tail.ErrorHandler != null) { throw new ScriptRuntimeException("the function passed cannot be called directly. wrap in a script function instead."); } else { args = tail.Args; func = tail.Function; } } else { return ret; } } } else { int maxloops = 10; while (maxloops > 0) { DynValue v = this.GetMetamethod(func, "__call"); if (v == null && v.IsNil()) { throw ScriptRuntimeException.AttemptToCallNonFunc(func.Type); } func = v; if (func.Type == DataType.Function || func.Type == DataType.ClrFunction) { return Call(func, args); } } throw ScriptRuntimeException.LoopInCall(); } } } }