-
Notifications
You must be signed in to change notification settings - Fork 242
Expand file tree
/
Copy pathScriptExecutionContext.cs
More file actions
280 lines (247 loc) · 7.76 KB
/
Copy pathScriptExecutionContext.cs
File metadata and controls
280 lines (247 loc) · 7.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
using System;
using MoonSharp.Interpreter.Debugging;
using MoonSharp.Interpreter.Execution.VM;
using MoonSharp.Interpreter.Interop.LuaStateInterop;
namespace MoonSharp.Interpreter
{
/// <summary>
/// Class giving access to details of the environment where the script is executing
/// </summary>
public class ScriptExecutionContext : IScriptPrivateResource
{
Processor m_Processor;
CallbackFunction m_Callback;
internal ScriptExecutionContext(Processor p, CallbackFunction callBackFunction, SourceRef sourceRef, bool isDynamic = false)
{
IsDynamicExecution = isDynamic;
m_Processor = p;
m_Callback = callBackFunction;
CallingLocation = sourceRef;
}
/// <summary>
/// Gets a value indicating whether this instance is running a dynamic execution.
/// Under a dynamic execution, most methods of ScriptExecutionContext are not reliable as the
/// processing engine of the script is not "really" running or is not available.
/// </summary>
public bool IsDynamicExecution
{
get;
private set;
}
/// <summary>
/// Gets the location of the code calling back
/// </summary>
public SourceRef CallingLocation
{
get;
private set;
}
/// <summary>
/// Gets or sets the additional data associated to this CLR function call.
/// </summary>
public object AdditionalData
{
get { return (m_Callback != null) ? m_Callback.AdditionalData : null; }
set
{
if (m_Callback == null) throw new InvalidOperationException("Cannot set additional data on a context which has no callback");
m_Callback.AdditionalData = value;
}
}
public SourceRef GetFunctionSourceCodeRef(Closure fn)
{
var i = fn.EntryPointByteCodeLocation;
return m_Processor.FindMeta(ref i).SourceCodeRef;
}
public string GetFunctionName(Closure fn)
{
var i = fn.EntryPointByteCodeLocation;
return m_Processor.FindMeta(ref i).Name;
}
/// <summary>
/// Gets the metatable associated with the given value.
/// </summary>
/// <param name="value">The value.</param>
/// <returns></returns>
public Table GetMetatable(DynValue value)
{
return m_Processor.GetMetatable(value);
}
/// <summary>
/// Gets the specified metamethod associated with the given value.
/// </summary>
/// <param name="value">The value.</param>
/// <param name="metamethod">The metamethod name.</param>
/// <returns></returns>
public DynValue GetMetamethod(DynValue value, string metamethod)
{
return m_Processor.GetMetamethod(value, metamethod);
}
/// <summary>
/// prepares a tail call request for the specified metamethod, or null if no metamethod is found.
/// </summary>
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);
}
/// <summary>
/// Gets the metamethod to be used for a binary operation using op1 and op2.
/// </summary>
public DynValue GetBinaryMetamethod(DynValue op1, DynValue op2, string eventName)
{
return m_Processor.GetBinaryMetamethod(op1, op2, eventName);
}
/// <summary>
/// Gets the script object associated with this request
/// </summary>
/// <returns></returns>
public Script GetScript()
{
return m_Processor.GetScript();
}
/// <summary>
/// Gets the coroutine which is performing the call
/// </summary>
public Coroutine GetCallingCoroutine()
{
return m_Processor.AssociatedCoroutine;
}
/// <summary>
/// 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
/// </summary>
/// <param name="args">The arguments.</param>
/// <param name="functionName">Name of the function - for error messages.</param>
/// <param name="callback">The callback.</param>
/// <returns></returns>
public DynValue EmulateClassicCall(CallbackArguments args, string functionName, Func<LuaState, int> callback)
{
LuaState L = new LuaState(this, args, functionName);
int retvals = callback(L);
return L.GetReturnValue(retvals);
}
/// <summary>
/// Calls the specified function, supporting most cases. The called function must not yield.
/// </summary>
/// <param name="func">The function; it must be a Function or ClrFunction or have a call metamethod defined.</param>
/// <param name="args">The arguments.</param>
/// <returns></returns>
/// <exception cref="ScriptRuntimeException">If the function yields, returns a tail call request with continuations/handlers or, of course, if it encounters errors.</exception>
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();
}
}
/// <summary>
/// Tries to get the reference of a symbol in the current execution state
/// </summary>
public DynValue EvaluateSymbol(SymbolRef symref)
{
if (symref == null)
return DynValue.Nil;
return m_Processor.GetGenericSymbol(symref);
}
/// <summary>
/// Tries to get the value of a symbol in the current execution state
/// </summary>
public DynValue EvaluateSymbolByName(string symbol)
{
return this.EvaluateSymbol(this.FindSymbolByName(symbol));
}
/// <summary>
/// Finds a symbol by name in the current execution state
/// </summary>
public SymbolRef FindSymbolByName(string symbol)
{
return m_Processor.FindSymbolByName(symbol);
}
/// <summary>
/// Gets the current global env, or null if not found.
/// </summary>
public Table CurrentGlobalEnv
{
get
{
DynValue env = EvaluateSymbolByName(WellKnownSymbols.ENV);
if (env == null || env.Type != DataType.Table)
return null;
else return env.Table;
}
}
/// <summary>
/// Performs a message decoration before unwinding after an error. To be used in the implementation of xpcall like functions.
/// </summary>
/// <param name="messageHandler">The message handler.</param>
/// <param name="exception">The exception.</param>
public void PerformMessageDecorationBeforeUnwind(DynValue messageHandler, ScriptRuntimeException exception)
{
if (messageHandler != null)
exception.DecoratedMessage = m_Processor.PerformMessageDecorationBeforeUnwind(messageHandler, exception.Message, CallingLocation);
else
exception.DecoratedMessage = exception.Message;
}
/// <summary>
/// Gets the script owning this resource.
/// </summary>
/// <value>
/// The script owning this resource.
/// </value>
public Script OwnerScript
{
get { return this.GetScript(); }
}
}
}