diff options
author | UbitUmarov | 2018-02-23 14:52:34 +0000 |
---|---|---|
committer | UbitUmarov | 2018-02-23 14:52:34 +0000 |
commit | 2129d941acbc5f83aca4dc4c30a62d3226888136 (patch) | |
tree | e12f2391978c923ef780f558ee5a32d857ee9124 /OpenSim/Region/ScriptEngine/YEngine/MMRScriptObjWriter.cs | |
parent | Merge branch 'master' into httptests (diff) | |
download | opensim-SC-2129d941acbc5f83aca4dc4c30a62d3226888136.zip opensim-SC-2129d941acbc5f83aca4dc4c30a62d3226888136.tar.gz opensim-SC-2129d941acbc5f83aca4dc4c30a62d3226888136.tar.bz2 opensim-SC-2129d941acbc5f83aca4dc4c30a62d3226888136.tar.xz |
rename XMREngine as Yengine (still not all done), big mess source formating changes, move state files to proper folder, fix a source file locking on errors, more changes for cross platform including from Mike,... yes yes i know a messy commit
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/ScriptEngine/YEngine/MMRScriptObjWriter.cs | 1040 |
1 files changed, 1040 insertions, 0 deletions
diff --git a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptObjWriter.cs b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptObjWriter.cs new file mode 100644 index 0000000..b87bc72 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptObjWriter.cs | |||
@@ -0,0 +1,1040 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using OpenSim.Region.ScriptEngine.Shared.ScriptBase; | ||
29 | using System; | ||
30 | using System.Collections.Generic; | ||
31 | using System.IO; | ||
32 | using System.Reflection; | ||
33 | using System.Reflection.Emit; | ||
34 | using System.Text; | ||
35 | |||
36 | using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; | ||
37 | using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; | ||
38 | using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; | ||
39 | using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; | ||
40 | using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; | ||
41 | using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; | ||
42 | using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; | ||
43 | |||
44 | /** | ||
45 | * @brief Wrapper class for ILGenerator. | ||
46 | * It writes the object code to a file and can then make real ILGenerator calls | ||
47 | * based on the file's contents. | ||
48 | */ | ||
49 | namespace OpenSim.Region.ScriptEngine.Yengine | ||
50 | { | ||
51 | public enum ScriptObjWriterCode: byte | ||
52 | { | ||
53 | BegMethod, EndMethod, TheEnd, | ||
54 | DclLabel, DclLocal, DclMethod, MarkLabel, | ||
55 | EmitNull, EmitField, EmitLocal, EmitType, EmitLabel, EmitMethodExt, | ||
56 | EmitMethodInt, EmitCtor, EmitDouble, EmitFloat, EmitInteger, EmitString, | ||
57 | EmitLabels, | ||
58 | BegExcBlk, BegCatBlk, BegFinBlk, EndExcBlk | ||
59 | } | ||
60 | |||
61 | public class ScriptObjWriter: ScriptMyILGen | ||
62 | { | ||
63 | private static Dictionary<short, OpCode> opCodes = PopulateOpCodes(); | ||
64 | private static Dictionary<string, Type> string2Type = PopulateS2T(); | ||
65 | private static Dictionary<Type, string> type2String = PopulateT2S(); | ||
66 | |||
67 | private static MethodInfo monoGetCurrentOffset = typeof(ILGenerator).GetMethod("Mono_GetCurrentOffset", | ||
68 | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, | ||
69 | new Type[] { typeof(ILGenerator) }, null); | ||
70 | |||
71 | private static readonly OpCode[] opCodesLdcI4M1P8 = new OpCode[] { | ||
72 | OpCodes.Ldc_I4_M1, OpCodes.Ldc_I4_0, OpCodes.Ldc_I4_1, OpCodes.Ldc_I4_2, OpCodes.Ldc_I4_3, | ||
73 | OpCodes.Ldc_I4_4, OpCodes.Ldc_I4_5, OpCodes.Ldc_I4_6, OpCodes.Ldc_I4_7, OpCodes.Ldc_I4_8 | ||
74 | }; | ||
75 | |||
76 | private BinaryWriter objFileWriter; | ||
77 | private string lastErrorAtFile = ""; | ||
78 | private int lastErrorAtLine = 0; | ||
79 | private int lastErrorAtPosn = 0; | ||
80 | |||
81 | private Dictionary<Type, string> sdTypesRev = new Dictionary<Type, string>(); | ||
82 | public int labelNumber = 0; | ||
83 | public int localNumber = 0; | ||
84 | |||
85 | private string _methName; | ||
86 | public string methName | ||
87 | { | ||
88 | get | ||
89 | { | ||
90 | return _methName; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | public Type retType; | ||
95 | public Type[] argTypes; | ||
96 | |||
97 | /** | ||
98 | * @brief Begin function declaration | ||
99 | * @param sdTypes = script-defined types | ||
100 | * @param methName = name of the method being declared, eg, "Verify(array,list,string)" | ||
101 | * @param retType = its return value type | ||
102 | * @param argTypes[] = its argument types | ||
103 | * @param objFileWriter = file to write its object code to | ||
104 | * | ||
105 | * After calling this function, the following functions should be called: | ||
106 | * this.BegMethod (); | ||
107 | * this.<as required> (); | ||
108 | * this.EndMethod (); | ||
109 | * | ||
110 | * The design of this object is such that many constructors may be called, | ||
111 | * but once a BegMethod() is called for one of the objects, no method may | ||
112 | * called for any of the other objects until EndMethod() is called (or it | ||
113 | * would break up the object stream for that method). But we need to have | ||
114 | * many constructors possible so we get function headers at the beginning | ||
115 | * of the object file in case there are forward references to the functions. | ||
116 | */ | ||
117 | public ScriptObjWriter(TokenScript tokenScript, string methName, Type retType, Type[] argTypes, string[] argNames, BinaryWriter objFileWriter) | ||
118 | { | ||
119 | this._methName = methName; | ||
120 | this.retType = retType; | ||
121 | this.argTypes = argTypes; | ||
122 | this.objFileWriter = objFileWriter; | ||
123 | |||
124 | /* | ||
125 | * Build list that translates system-defined types to script defined types. | ||
126 | */ | ||
127 | foreach(TokenDeclSDType sdt in tokenScript.sdSrcTypesValues) | ||
128 | { | ||
129 | Type sys = sdt.GetSysType(); | ||
130 | if(sys != null) | ||
131 | sdTypesRev[sys] = sdt.longName.val; | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * This tells the reader to call 'new DynamicMethod()' to create | ||
136 | * the function header. Then any forward reference calls to this | ||
137 | * method will have a MethodInfo struct to call. | ||
138 | */ | ||
139 | objFileWriter.Write((byte)ScriptObjWriterCode.DclMethod); | ||
140 | objFileWriter.Write(methName); | ||
141 | objFileWriter.Write(GetStrFromType(retType)); | ||
142 | |||
143 | int nArgs = argTypes.Length; | ||
144 | objFileWriter.Write(nArgs); | ||
145 | for(int i = 0; i < nArgs; i++) | ||
146 | { | ||
147 | objFileWriter.Write(GetStrFromType(argTypes[i])); | ||
148 | objFileWriter.Write(argNames[i]); | ||
149 | } | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * @brief Begin outputting object code for the function | ||
154 | */ | ||
155 | public void BegMethod() | ||
156 | { | ||
157 | /* | ||
158 | * This tells the reader to call methodInfo.GetILGenerator() | ||
159 | * so it can start writing CIL code for the method. | ||
160 | */ | ||
161 | objFileWriter.Write((byte)ScriptObjWriterCode.BegMethod); | ||
162 | objFileWriter.Write(methName); | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * @brief End of object code for the function | ||
167 | */ | ||
168 | public void EndMethod() | ||
169 | { | ||
170 | /* | ||
171 | * This tells the reader that all code for the method has | ||
172 | * been written and so it will typically call CreateDelegate() | ||
173 | * to finalize the method and create an entrypoint. | ||
174 | */ | ||
175 | objFileWriter.Write((byte)ScriptObjWriterCode.EndMethod); | ||
176 | |||
177 | objFileWriter = null; | ||
178 | } | ||
179 | |||
180 | /** | ||
181 | * @brief Declare a local variable for use by the function | ||
182 | */ | ||
183 | public ScriptMyLocal DeclareLocal(Type type, string name) | ||
184 | { | ||
185 | ScriptMyLocal myLocal = new ScriptMyLocal(); | ||
186 | myLocal.type = type; | ||
187 | myLocal.name = name; | ||
188 | myLocal.number = localNumber++; | ||
189 | myLocal.isReferenced = true; // so ScriptCollector won't optimize references away | ||
190 | return DeclareLocal(myLocal); | ||
191 | } | ||
192 | public ScriptMyLocal DeclareLocal(ScriptMyLocal myLocal) | ||
193 | { | ||
194 | objFileWriter.Write((byte)ScriptObjWriterCode.DclLocal); | ||
195 | objFileWriter.Write(myLocal.number); | ||
196 | objFileWriter.Write(myLocal.name); | ||
197 | objFileWriter.Write(GetStrFromType(myLocal.type)); | ||
198 | return myLocal; | ||
199 | } | ||
200 | |||
201 | /** | ||
202 | * @brief Define a label for use by the function | ||
203 | */ | ||
204 | public ScriptMyLabel DefineLabel(string name) | ||
205 | { | ||
206 | ScriptMyLabel myLabel = new ScriptMyLabel(); | ||
207 | myLabel.name = name; | ||
208 | myLabel.number = labelNumber++; | ||
209 | return DefineLabel(myLabel); | ||
210 | } | ||
211 | public ScriptMyLabel DefineLabel(ScriptMyLabel myLabel) | ||
212 | { | ||
213 | objFileWriter.Write((byte)ScriptObjWriterCode.DclLabel); | ||
214 | objFileWriter.Write(myLabel.number); | ||
215 | objFileWriter.Write(myLabel.name); | ||
216 | return myLabel; | ||
217 | } | ||
218 | |||
219 | /** | ||
220 | * @brief try/catch blocks. | ||
221 | */ | ||
222 | public void BeginExceptionBlock() | ||
223 | { | ||
224 | objFileWriter.Write((byte)ScriptObjWriterCode.BegExcBlk); | ||
225 | } | ||
226 | |||
227 | public void BeginCatchBlock(Type excType) | ||
228 | { | ||
229 | objFileWriter.Write((byte)ScriptObjWriterCode.BegCatBlk); | ||
230 | objFileWriter.Write(GetStrFromType(excType)); | ||
231 | } | ||
232 | |||
233 | public void BeginFinallyBlock() | ||
234 | { | ||
235 | objFileWriter.Write((byte)ScriptObjWriterCode.BegFinBlk); | ||
236 | } | ||
237 | |||
238 | public void EndExceptionBlock() | ||
239 | { | ||
240 | objFileWriter.Write((byte)ScriptObjWriterCode.EndExcBlk); | ||
241 | } | ||
242 | |||
243 | public void Emit(Token errorAt, OpCode opcode) | ||
244 | { | ||
245 | objFileWriter.Write((byte)ScriptObjWriterCode.EmitNull); | ||
246 | WriteOpCode(errorAt, opcode); | ||
247 | } | ||
248 | |||
249 | public void Emit(Token errorAt, OpCode opcode, FieldInfo field) | ||
250 | { | ||
251 | objFileWriter.Write((byte)ScriptObjWriterCode.EmitField); | ||
252 | WriteOpCode(errorAt, opcode); | ||
253 | objFileWriter.Write(GetStrFromType(field.ReflectedType)); | ||
254 | objFileWriter.Write(field.Name); | ||
255 | } | ||
256 | |||
257 | public void Emit(Token errorAt, OpCode opcode, ScriptMyLocal myLocal) | ||
258 | { | ||
259 | objFileWriter.Write((byte)ScriptObjWriterCode.EmitLocal); | ||
260 | WriteOpCode(errorAt, opcode); | ||
261 | objFileWriter.Write(myLocal.number); | ||
262 | } | ||
263 | |||
264 | public void Emit(Token errorAt, OpCode opcode, Type type) | ||
265 | { | ||
266 | objFileWriter.Write((byte)ScriptObjWriterCode.EmitType); | ||
267 | WriteOpCode(errorAt, opcode); | ||
268 | objFileWriter.Write(GetStrFromType(type)); | ||
269 | } | ||
270 | |||
271 | public void Emit(Token errorAt, OpCode opcode, ScriptMyLabel myLabel) | ||
272 | { | ||
273 | objFileWriter.Write((byte)ScriptObjWriterCode.EmitLabel); | ||
274 | WriteOpCode(errorAt, opcode); | ||
275 | objFileWriter.Write(myLabel.number); | ||
276 | } | ||
277 | |||
278 | public void Emit(Token errorAt, OpCode opcode, ScriptMyLabel[] myLabels) | ||
279 | { | ||
280 | objFileWriter.Write((byte)ScriptObjWriterCode.EmitLabels); | ||
281 | WriteOpCode(errorAt, opcode); | ||
282 | int nLabels = myLabels.Length; | ||
283 | objFileWriter.Write(nLabels); | ||
284 | for(int i = 0; i < nLabels; i++) | ||
285 | { | ||
286 | objFileWriter.Write(myLabels[i].number); | ||
287 | } | ||
288 | } | ||
289 | |||
290 | public void Emit(Token errorAt, OpCode opcode, ScriptObjWriter method) | ||
291 | { | ||
292 | if(method == null) | ||
293 | throw new ArgumentNullException("method"); | ||
294 | objFileWriter.Write((byte)ScriptObjWriterCode.EmitMethodInt); | ||
295 | WriteOpCode(errorAt, opcode); | ||
296 | objFileWriter.Write(method.methName); | ||
297 | } | ||
298 | |||
299 | public void Emit(Token errorAt, OpCode opcode, MethodInfo method) | ||
300 | { | ||
301 | objFileWriter.Write((byte)ScriptObjWriterCode.EmitMethodExt); | ||
302 | WriteOpCode(errorAt, opcode); | ||
303 | objFileWriter.Write(method.Name); | ||
304 | objFileWriter.Write(GetStrFromType(method.ReflectedType)); | ||
305 | ParameterInfo[] parms = method.GetParameters(); | ||
306 | int nArgs = parms.Length; | ||
307 | objFileWriter.Write(nArgs); | ||
308 | for(int i = 0; i < nArgs; i++) | ||
309 | { | ||
310 | objFileWriter.Write(GetStrFromType(parms[i].ParameterType)); | ||
311 | } | ||
312 | } | ||
313 | |||
314 | public void Emit(Token errorAt, OpCode opcode, ConstructorInfo ctor) | ||
315 | { | ||
316 | objFileWriter.Write((byte)ScriptObjWriterCode.EmitCtor); | ||
317 | WriteOpCode(errorAt, opcode); | ||
318 | objFileWriter.Write(GetStrFromType(ctor.ReflectedType)); | ||
319 | ParameterInfo[] parms = ctor.GetParameters(); | ||
320 | int nArgs = parms.Length; | ||
321 | objFileWriter.Write(nArgs); | ||
322 | for(int i = 0; i < nArgs; i++) | ||
323 | { | ||
324 | objFileWriter.Write(GetStrFromType(parms[i].ParameterType)); | ||
325 | } | ||
326 | } | ||
327 | |||
328 | public void Emit(Token errorAt, OpCode opcode, double value) | ||
329 | { | ||
330 | if(opcode != OpCodes.Ldc_R8) | ||
331 | { | ||
332 | throw new Exception("bad opcode " + opcode.ToString()); | ||
333 | } | ||
334 | objFileWriter.Write((byte)ScriptObjWriterCode.EmitDouble); | ||
335 | WriteOpCode(errorAt, opcode); | ||
336 | objFileWriter.Write(value); | ||
337 | } | ||
338 | |||
339 | public void Emit(Token errorAt, OpCode opcode, float value) | ||
340 | { | ||
341 | if(opcode != OpCodes.Ldc_R4) | ||
342 | { | ||
343 | throw new Exception("bad opcode " + opcode.ToString()); | ||
344 | } | ||
345 | objFileWriter.Write((byte)ScriptObjWriterCode.EmitFloat); | ||
346 | WriteOpCode(errorAt, opcode); | ||
347 | objFileWriter.Write(value); | ||
348 | } | ||
349 | |||
350 | public void Emit(Token errorAt, OpCode opcode, int value) | ||
351 | { | ||
352 | objFileWriter.Write((byte)ScriptObjWriterCode.EmitInteger); | ||
353 | WriteOpCode(errorAt, opcode); | ||
354 | objFileWriter.Write(value); | ||
355 | } | ||
356 | |||
357 | public void Emit(Token errorAt, OpCode opcode, string value) | ||
358 | { | ||
359 | objFileWriter.Write((byte)ScriptObjWriterCode.EmitString); | ||
360 | WriteOpCode(errorAt, opcode); | ||
361 | objFileWriter.Write(value); | ||
362 | } | ||
363 | |||
364 | /** | ||
365 | * @brief Declare that the target of a label is the next instruction. | ||
366 | */ | ||
367 | public void MarkLabel(ScriptMyLabel myLabel) | ||
368 | { | ||
369 | objFileWriter.Write((byte)ScriptObjWriterCode.MarkLabel); | ||
370 | objFileWriter.Write(myLabel.number); | ||
371 | } | ||
372 | |||
373 | /** | ||
374 | * @brief Write end-of-file marker to binary file. | ||
375 | */ | ||
376 | public static void TheEnd(BinaryWriter objFileWriter) | ||
377 | { | ||
378 | objFileWriter.Write((byte)ScriptObjWriterCode.TheEnd); | ||
379 | } | ||
380 | |||
381 | /** | ||
382 | * @brief Take an object file created by ScriptObjWriter() and convert it to a series of dynamic methods. | ||
383 | * @param sdTypes = script-defined types | ||
384 | * @param objReader = where to read object file from (as written by ScriptObjWriter above). | ||
385 | * @param scriptObjCode.EndMethod = called for each method defined at the end of the methods definition | ||
386 | * @param objectTokens = write disassemble/decompile data (or null if not wanted) | ||
387 | */ | ||
388 | public static void CreateObjCode(Dictionary<string, TokenDeclSDType> sdTypes, BinaryReader objReader, | ||
389 | ScriptObjCode scriptObjCode, ObjectTokens objectTokens) | ||
390 | { | ||
391 | Dictionary<string, DynamicMethod> methods = new Dictionary<string, DynamicMethod>(); | ||
392 | DynamicMethod method = null; | ||
393 | ILGenerator ilGen = null; | ||
394 | Dictionary<int, Label> labels = new Dictionary<int, Label>(); | ||
395 | Dictionary<int, LocalBuilder> locals = new Dictionary<int, LocalBuilder>(); | ||
396 | Dictionary<int, string> labelNames = new Dictionary<int, string>(); | ||
397 | Dictionary<int, string> localNames = new Dictionary<int, string>(); | ||
398 | object[] ilGenArg = new object[1]; | ||
399 | int offset = 0; | ||
400 | Dictionary<int, ScriptSrcLoc> srcLocs = null; | ||
401 | string srcFile = ""; | ||
402 | int srcLine = 0; | ||
403 | int srcPosn = 0; | ||
404 | |||
405 | while(true) | ||
406 | { | ||
407 | |||
408 | /* | ||
409 | * Get IL instruction offset at beginning of instruction. | ||
410 | */ | ||
411 | offset = 0; | ||
412 | if((ilGen != null) && (monoGetCurrentOffset != null)) | ||
413 | { | ||
414 | offset = (int)monoGetCurrentOffset.Invoke(null, ilGenArg); | ||
415 | } | ||
416 | |||
417 | /* | ||
418 | * Read and decode next internal format code from input file (.xmrobj file). | ||
419 | */ | ||
420 | ScriptObjWriterCode code = (ScriptObjWriterCode)objReader.ReadByte(); | ||
421 | switch(code) | ||
422 | { | ||
423 | |||
424 | /* | ||
425 | * Reached end-of-file so we are all done. | ||
426 | */ | ||
427 | case ScriptObjWriterCode.TheEnd: | ||
428 | { | ||
429 | return; | ||
430 | } | ||
431 | |||
432 | /* | ||
433 | * Beginning of method's contents. | ||
434 | * Method must have already been declared via DclMethod | ||
435 | * so all we need is its name to retrieve from methods[]. | ||
436 | */ | ||
437 | case ScriptObjWriterCode.BegMethod: | ||
438 | { | ||
439 | string methName = objReader.ReadString(); | ||
440 | |||
441 | method = methods[methName]; | ||
442 | ilGen = method.GetILGenerator(); | ||
443 | ilGenArg[0] = ilGen; | ||
444 | |||
445 | labels.Clear(); | ||
446 | locals.Clear(); | ||
447 | labelNames.Clear(); | ||
448 | localNames.Clear(); | ||
449 | |||
450 | srcLocs = new Dictionary<int, ScriptSrcLoc>(); | ||
451 | if(objectTokens != null) | ||
452 | objectTokens.BegMethod(method); | ||
453 | break; | ||
454 | } | ||
455 | |||
456 | /* | ||
457 | * End of method's contents (ie, an OpCodes.Ret was probably just output). | ||
458 | * Call the callback to tell it the method is complete, and it can do whatever | ||
459 | * it wants with the method. | ||
460 | */ | ||
461 | case ScriptObjWriterCode.EndMethod: | ||
462 | { | ||
463 | ilGen = null; | ||
464 | ilGenArg[0] = null; | ||
465 | scriptObjCode.EndMethod(method, srcLocs); | ||
466 | srcLocs = null; | ||
467 | if(objectTokens != null) | ||
468 | objectTokens.EndMethod(); | ||
469 | break; | ||
470 | } | ||
471 | |||
472 | /* | ||
473 | * Declare a label for branching to. | ||
474 | */ | ||
475 | case ScriptObjWriterCode.DclLabel: | ||
476 | { | ||
477 | int number = objReader.ReadInt32(); | ||
478 | string name = objReader.ReadString(); | ||
479 | |||
480 | labels.Add(number, ilGen.DefineLabel()); | ||
481 | labelNames.Add(number, name + "_" + number.ToString()); | ||
482 | if(objectTokens != null) | ||
483 | objectTokens.DefineLabel(number, name); | ||
484 | break; | ||
485 | } | ||
486 | |||
487 | /* | ||
488 | * Declare a local variable to store into. | ||
489 | */ | ||
490 | case ScriptObjWriterCode.DclLocal: | ||
491 | { | ||
492 | int number = objReader.ReadInt32(); | ||
493 | string name = objReader.ReadString(); | ||
494 | string type = objReader.ReadString(); | ||
495 | Type syType = GetTypeFromStr(sdTypes, type); | ||
496 | |||
497 | locals.Add(number, ilGen.DeclareLocal(syType)); | ||
498 | localNames.Add(number, name + "_" + number.ToString()); | ||
499 | if(objectTokens != null) | ||
500 | objectTokens.DefineLocal(number, name, type, syType); | ||
501 | break; | ||
502 | } | ||
503 | |||
504 | /* | ||
505 | * Declare a method that will subsequently be defined. | ||
506 | * We create the DynamicMethod object at this point in case there | ||
507 | * are forward references from other method bodies. | ||
508 | */ | ||
509 | case ScriptObjWriterCode.DclMethod: | ||
510 | { | ||
511 | string methName = objReader.ReadString(); | ||
512 | Type retType = GetTypeFromStr(sdTypes, objReader.ReadString()); | ||
513 | int nArgs = objReader.ReadInt32(); | ||
514 | |||
515 | Type[] argTypes = new Type[nArgs]; | ||
516 | string[] argNames = new string[nArgs]; | ||
517 | for(int i = 0; i < nArgs; i++) | ||
518 | { | ||
519 | argTypes[i] = GetTypeFromStr(sdTypes, objReader.ReadString()); | ||
520 | argNames[i] = objReader.ReadString(); | ||
521 | } | ||
522 | methods.Add(methName, new DynamicMethod(methName, retType, argTypes)); | ||
523 | if(objectTokens != null) | ||
524 | objectTokens.DefineMethod(methName, retType, argTypes, argNames); | ||
525 | break; | ||
526 | } | ||
527 | |||
528 | /* | ||
529 | * Mark a previously declared label at this spot. | ||
530 | */ | ||
531 | case ScriptObjWriterCode.MarkLabel: | ||
532 | { | ||
533 | int number = objReader.ReadInt32(); | ||
534 | |||
535 | ilGen.MarkLabel(labels[number]); | ||
536 | |||
537 | if(objectTokens != null) | ||
538 | objectTokens.MarkLabel(offset, number); | ||
539 | break; | ||
540 | } | ||
541 | |||
542 | /* | ||
543 | * Try/Catch blocks. | ||
544 | */ | ||
545 | case ScriptObjWriterCode.BegExcBlk: | ||
546 | { | ||
547 | ilGen.BeginExceptionBlock(); | ||
548 | if(objectTokens != null) | ||
549 | objectTokens.BegExcBlk(offset); | ||
550 | break; | ||
551 | } | ||
552 | |||
553 | case ScriptObjWriterCode.BegCatBlk: | ||
554 | { | ||
555 | Type excType = GetTypeFromStr(sdTypes, objReader.ReadString()); | ||
556 | ilGen.BeginCatchBlock(excType); | ||
557 | if(objectTokens != null) | ||
558 | objectTokens.BegCatBlk(offset, excType); | ||
559 | break; | ||
560 | } | ||
561 | |||
562 | case ScriptObjWriterCode.BegFinBlk: | ||
563 | { | ||
564 | ilGen.BeginFinallyBlock(); | ||
565 | if(objectTokens != null) | ||
566 | objectTokens.BegFinBlk(offset); | ||
567 | break; | ||
568 | } | ||
569 | |||
570 | case ScriptObjWriterCode.EndExcBlk: | ||
571 | { | ||
572 | ilGen.EndExceptionBlock(); | ||
573 | if(objectTokens != null) | ||
574 | objectTokens.EndExcBlk(offset); | ||
575 | break; | ||
576 | } | ||
577 | |||
578 | /* | ||
579 | * Emit an opcode with no operand. | ||
580 | */ | ||
581 | case ScriptObjWriterCode.EmitNull: | ||
582 | { | ||
583 | OpCode opCode = ReadOpCode(objReader, ref srcFile, ref srcLine, ref srcPosn); | ||
584 | |||
585 | SaveSrcLoc(srcLocs, offset, srcFile, srcLine, srcPosn); | ||
586 | ilGen.Emit(opCode); | ||
587 | |||
588 | if(objectTokens != null) | ||
589 | objectTokens.EmitNull(offset, opCode); | ||
590 | break; | ||
591 | } | ||
592 | |||
593 | /* | ||
594 | * Emit an opcode with a FieldInfo operand. | ||
595 | */ | ||
596 | case ScriptObjWriterCode.EmitField: | ||
597 | { | ||
598 | OpCode opCode = ReadOpCode(objReader, ref srcFile, ref srcLine, ref srcPosn); | ||
599 | Type reflectedType = GetTypeFromStr(sdTypes, objReader.ReadString()); | ||
600 | string fieldName = objReader.ReadString(); | ||
601 | |||
602 | FieldInfo field = reflectedType.GetField(fieldName); | ||
603 | SaveSrcLoc(srcLocs, offset, srcFile, srcLine, srcPosn); | ||
604 | ilGen.Emit(opCode, field); | ||
605 | |||
606 | if(objectTokens != null) | ||
607 | objectTokens.EmitField(offset, opCode, field); | ||
608 | break; | ||
609 | } | ||
610 | |||
611 | /* | ||
612 | * Emit an opcode with a LocalBuilder operand. | ||
613 | */ | ||
614 | case ScriptObjWriterCode.EmitLocal: | ||
615 | { | ||
616 | OpCode opCode = ReadOpCode(objReader, ref srcFile, ref srcLine, ref srcPosn); | ||
617 | int number = objReader.ReadInt32(); | ||
618 | SaveSrcLoc(srcLocs, offset, srcFile, srcLine, srcPosn); | ||
619 | ilGen.Emit(opCode, locals[number]); | ||
620 | |||
621 | if(objectTokens != null) | ||
622 | objectTokens.EmitLocal(offset, opCode, number); | ||
623 | break; | ||
624 | } | ||
625 | |||
626 | /* | ||
627 | * Emit an opcode with a Type operand. | ||
628 | */ | ||
629 | case ScriptObjWriterCode.EmitType: | ||
630 | { | ||
631 | OpCode opCode = ReadOpCode(objReader, ref srcFile, ref srcLine, ref srcPosn); | ||
632 | string name = objReader.ReadString(); | ||
633 | Type type = GetTypeFromStr(sdTypes, name); | ||
634 | |||
635 | SaveSrcLoc(srcLocs, offset, srcFile, srcLine, srcPosn); | ||
636 | ilGen.Emit(opCode, type); | ||
637 | |||
638 | if(objectTokens != null) | ||
639 | objectTokens.EmitType(offset, opCode, type); | ||
640 | break; | ||
641 | } | ||
642 | |||
643 | /* | ||
644 | * Emit an opcode with a Label operand. | ||
645 | */ | ||
646 | case ScriptObjWriterCode.EmitLabel: | ||
647 | { | ||
648 | OpCode opCode = ReadOpCode(objReader, ref srcFile, ref srcLine, ref srcPosn); | ||
649 | int number = objReader.ReadInt32(); | ||
650 | |||
651 | SaveSrcLoc(srcLocs, offset, srcFile, srcLine, srcPosn); | ||
652 | ilGen.Emit(opCode, labels[number]); | ||
653 | |||
654 | if(objectTokens != null) | ||
655 | objectTokens.EmitLabel(offset, opCode, number); | ||
656 | break; | ||
657 | } | ||
658 | |||
659 | /* | ||
660 | * Emit an opcode with a Label array operand. | ||
661 | */ | ||
662 | case ScriptObjWriterCode.EmitLabels: | ||
663 | { | ||
664 | OpCode opCode = ReadOpCode(objReader, ref srcFile, ref srcLine, ref srcPosn); | ||
665 | int nLabels = objReader.ReadInt32(); | ||
666 | Label[] lbls = new Label[nLabels]; | ||
667 | int[] nums = new int[nLabels]; | ||
668 | for(int i = 0; i < nLabels; i++) | ||
669 | { | ||
670 | nums[i] = objReader.ReadInt32(); | ||
671 | lbls[i] = labels[nums[i]]; | ||
672 | } | ||
673 | |||
674 | SaveSrcLoc(srcLocs, offset, srcFile, srcLine, srcPosn); | ||
675 | ilGen.Emit(opCode, lbls); | ||
676 | |||
677 | if(objectTokens != null) | ||
678 | objectTokens.EmitLabels(offset, opCode, nums); | ||
679 | break; | ||
680 | } | ||
681 | |||
682 | /* | ||
683 | * Emit an opcode with a MethodInfo operand (such as a call) of an external function. | ||
684 | */ | ||
685 | case ScriptObjWriterCode.EmitMethodExt: | ||
686 | { | ||
687 | OpCode opCode = ReadOpCode(objReader, ref srcFile, ref srcLine, ref srcPosn); | ||
688 | string methName = objReader.ReadString(); | ||
689 | Type methType = GetTypeFromStr(sdTypes, objReader.ReadString()); | ||
690 | int nArgs = objReader.ReadInt32(); | ||
691 | |||
692 | Type[] argTypes = new Type[nArgs]; | ||
693 | for(int i = 0; i < nArgs; i++) | ||
694 | { | ||
695 | argTypes[i] = GetTypeFromStr(sdTypes, objReader.ReadString()); | ||
696 | } | ||
697 | MethodInfo methInfo = methType.GetMethod(methName, argTypes); | ||
698 | SaveSrcLoc(srcLocs, offset, srcFile, srcLine, srcPosn); | ||
699 | ilGen.Emit(opCode, methInfo); | ||
700 | |||
701 | if(objectTokens != null) | ||
702 | objectTokens.EmitMethod(offset, opCode, methInfo); | ||
703 | break; | ||
704 | } | ||
705 | |||
706 | /* | ||
707 | * Emit an opcode with a MethodInfo operand of an internal function | ||
708 | * (previously declared via DclMethod). | ||
709 | */ | ||
710 | case ScriptObjWriterCode.EmitMethodInt: | ||
711 | { | ||
712 | OpCode opCode = ReadOpCode(objReader, ref srcFile, ref srcLine, ref srcPosn); | ||
713 | string methName = objReader.ReadString(); | ||
714 | |||
715 | MethodInfo methInfo = methods[methName]; | ||
716 | SaveSrcLoc(srcLocs, offset, srcFile, srcLine, srcPosn); | ||
717 | ilGen.Emit(opCode, methInfo); | ||
718 | |||
719 | if(objectTokens != null) | ||
720 | objectTokens.EmitMethod(offset, opCode, methInfo); | ||
721 | break; | ||
722 | } | ||
723 | |||
724 | /* | ||
725 | * Emit an opcode with a ConstructorInfo operand. | ||
726 | */ | ||
727 | case ScriptObjWriterCode.EmitCtor: | ||
728 | { | ||
729 | OpCode opCode = ReadOpCode(objReader, ref srcFile, ref srcLine, ref srcPosn); | ||
730 | Type ctorType = GetTypeFromStr(sdTypes, objReader.ReadString()); | ||
731 | int nArgs = objReader.ReadInt32(); | ||
732 | Type[] argTypes = new Type[nArgs]; | ||
733 | for(int i = 0; i < nArgs; i++) | ||
734 | { | ||
735 | argTypes[i] = GetTypeFromStr(sdTypes, objReader.ReadString()); | ||
736 | } | ||
737 | |||
738 | ConstructorInfo ctorInfo = ctorType.GetConstructor(argTypes); | ||
739 | SaveSrcLoc(srcLocs, offset, srcFile, srcLine, srcPosn); | ||
740 | ilGen.Emit(opCode, ctorInfo); | ||
741 | |||
742 | if(objectTokens != null) | ||
743 | objectTokens.EmitCtor(offset, opCode, ctorInfo); | ||
744 | break; | ||
745 | } | ||
746 | |||
747 | /* | ||
748 | * Emit an opcode with a constant operand of various types. | ||
749 | */ | ||
750 | case ScriptObjWriterCode.EmitDouble: | ||
751 | { | ||
752 | OpCode opCode = ReadOpCode(objReader, ref srcFile, ref srcLine, ref srcPosn); | ||
753 | double value = objReader.ReadDouble(); | ||
754 | |||
755 | if(opCode != OpCodes.Ldc_R8) | ||
756 | { | ||
757 | throw new Exception("bad opcode " + opCode.ToString()); | ||
758 | } | ||
759 | SaveSrcLoc(srcLocs, offset, srcFile, srcLine, srcPosn); | ||
760 | ilGen.Emit(opCode, value); | ||
761 | |||
762 | if(objectTokens != null) | ||
763 | objectTokens.EmitDouble(offset, opCode, value); | ||
764 | break; | ||
765 | } | ||
766 | |||
767 | case ScriptObjWriterCode.EmitFloat: | ||
768 | { | ||
769 | OpCode opCode = ReadOpCode(objReader, ref srcFile, ref srcLine, ref srcPosn); | ||
770 | float value = objReader.ReadSingle(); | ||
771 | |||
772 | if(opCode != OpCodes.Ldc_R4) | ||
773 | { | ||
774 | throw new Exception("bad opcode " + opCode.ToString()); | ||
775 | } | ||
776 | SaveSrcLoc(srcLocs, offset, srcFile, srcLine, srcPosn); | ||
777 | ilGen.Emit(opCode, value); | ||
778 | |||
779 | if(objectTokens != null) | ||
780 | objectTokens.EmitFloat(offset, opCode, value); | ||
781 | break; | ||
782 | } | ||
783 | |||
784 | case ScriptObjWriterCode.EmitInteger: | ||
785 | { | ||
786 | OpCode opCode = ReadOpCode(objReader, ref srcFile, ref srcLine, ref srcPosn); | ||
787 | int value = objReader.ReadInt32(); | ||
788 | |||
789 | SaveSrcLoc(srcLocs, offset, srcFile, srcLine, srcPosn); | ||
790 | |||
791 | if(opCode == OpCodes.Ldc_I4) | ||
792 | { | ||
793 | if((value >= -1) && (value <= 8)) | ||
794 | { | ||
795 | opCode = opCodesLdcI4M1P8[value + 1]; | ||
796 | ilGen.Emit(opCode); | ||
797 | if(objectTokens != null) | ||
798 | objectTokens.EmitNull(offset, opCode); | ||
799 | break; | ||
800 | } | ||
801 | if((value >= 0) && (value <= 127)) | ||
802 | { | ||
803 | opCode = OpCodes.Ldc_I4_S; | ||
804 | ilGen.Emit(OpCodes.Ldc_I4_S, (sbyte)value); | ||
805 | goto pemitint; | ||
806 | } | ||
807 | } | ||
808 | |||
809 | ilGen.Emit(opCode, value); | ||
810 | pemitint: | ||
811 | if(objectTokens != null) | ||
812 | objectTokens.EmitInteger(offset, opCode, value); | ||
813 | break; | ||
814 | } | ||
815 | |||
816 | case ScriptObjWriterCode.EmitString: | ||
817 | { | ||
818 | OpCode opCode = ReadOpCode(objReader, ref srcFile, ref srcLine, ref srcPosn); | ||
819 | string value = objReader.ReadString(); | ||
820 | |||
821 | SaveSrcLoc(srcLocs, offset, srcFile, srcLine, srcPosn); | ||
822 | ilGen.Emit(opCode, value); | ||
823 | |||
824 | if(objectTokens != null) | ||
825 | objectTokens.EmitString(offset, opCode, value); | ||
826 | break; | ||
827 | } | ||
828 | |||
829 | /* | ||
830 | * Who knows what? | ||
831 | */ | ||
832 | default: | ||
833 | throw new Exception("bad ScriptObjWriterCode " + ((byte)code).ToString()); | ||
834 | } | ||
835 | } | ||
836 | } | ||
837 | |||
838 | /** | ||
839 | * @brief Generate array to quickly translate OpCode.Value to full OpCode struct. | ||
840 | */ | ||
841 | private static Dictionary<short, OpCode> PopulateOpCodes() | ||
842 | { | ||
843 | Dictionary<short, OpCode> opCodeDict = new Dictionary<short, OpCode>(); | ||
844 | FieldInfo[] fields = typeof(OpCodes).GetFields(); | ||
845 | for(int i = 0; i < fields.Length; i++) | ||
846 | { | ||
847 | OpCode opcode = (OpCode)fields[i].GetValue(null); | ||
848 | opCodeDict.Add(opcode.Value, opcode); | ||
849 | } | ||
850 | return opCodeDict; | ||
851 | } | ||
852 | |||
853 | /** | ||
854 | * @brief Write opcode out to file. | ||
855 | */ | ||
856 | private void WriteOpCode(Token errorAt, OpCode opcode) | ||
857 | { | ||
858 | if(errorAt == null) | ||
859 | { | ||
860 | objFileWriter.Write(""); | ||
861 | objFileWriter.Write(lastErrorAtLine); | ||
862 | objFileWriter.Write(lastErrorAtPosn); | ||
863 | } | ||
864 | else | ||
865 | { | ||
866 | if(errorAt.file != lastErrorAtFile) | ||
867 | { | ||
868 | objFileWriter.Write(errorAt.file); | ||
869 | lastErrorAtFile = errorAt.file; | ||
870 | } | ||
871 | else | ||
872 | { | ||
873 | objFileWriter.Write(""); | ||
874 | } | ||
875 | objFileWriter.Write(errorAt.line); | ||
876 | objFileWriter.Write(errorAt.posn); | ||
877 | lastErrorAtLine = errorAt.line; | ||
878 | lastErrorAtPosn = errorAt.posn; | ||
879 | } | ||
880 | objFileWriter.Write(opcode.Value); | ||
881 | } | ||
882 | |||
883 | /** | ||
884 | * @brief Read opcode in from file. | ||
885 | */ | ||
886 | private static OpCode ReadOpCode(BinaryReader objReader, ref string srcFile, ref int srcLine, ref int srcPosn) | ||
887 | { | ||
888 | string f = objReader.ReadString(); | ||
889 | if(f != "") | ||
890 | srcFile = f; | ||
891 | srcLine = objReader.ReadInt32(); | ||
892 | srcPosn = objReader.ReadInt32(); | ||
893 | |||
894 | short value = objReader.ReadInt16(); | ||
895 | return opCodes[value]; | ||
896 | } | ||
897 | |||
898 | /** | ||
899 | * @brief Save an IL_offset -> source location translation entry | ||
900 | * @param srcLocs = saved entries for the current function | ||
901 | * @param offset = offset in IL object code for next instruction | ||
902 | * @param src{File,Line,Posn} = location in source file corresponding to opcode | ||
903 | * @returns with entry added to srcLocs | ||
904 | */ | ||
905 | private static void SaveSrcLoc(Dictionary<int, ScriptSrcLoc> srcLocs, int offset, string srcFile, int srcLine, int srcPosn) | ||
906 | { | ||
907 | ScriptSrcLoc srcLoc = new ScriptSrcLoc(); | ||
908 | srcLoc.file = srcFile; | ||
909 | srcLoc.line = srcLine; | ||
910 | srcLoc.posn = srcPosn; | ||
911 | srcLocs[offset] = srcLoc; | ||
912 | } | ||
913 | |||
914 | /** | ||
915 | * @brief Create type<->string conversions. | ||
916 | * Using Type.AssemblyQualifiedName is horribly inefficient | ||
917 | * and all our types should be known. | ||
918 | */ | ||
919 | private static Dictionary<string, Type> PopulateS2T() | ||
920 | { | ||
921 | Dictionary<string, Type> s2t = new Dictionary<string, Type>(); | ||
922 | |||
923 | s2t.Add("badcallx", typeof(ScriptBadCallNoException)); | ||
924 | s2t.Add("binopstr", typeof(BinOpStr)); | ||
925 | s2t.Add("bool", typeof(bool)); | ||
926 | s2t.Add("char", typeof(char)); | ||
927 | s2t.Add("delegate", typeof(Delegate)); | ||
928 | s2t.Add("delarr[]", typeof(Delegate[])); | ||
929 | s2t.Add("double", typeof(double)); | ||
930 | s2t.Add("exceptn", typeof(Exception)); | ||
931 | s2t.Add("float", typeof(float)); | ||
932 | s2t.Add("htlist", typeof(HeapTrackerList)); | ||
933 | s2t.Add("htobject", typeof(HeapTrackerObject)); | ||
934 | s2t.Add("htstring", typeof(HeapTrackerString)); | ||
935 | s2t.Add("inlfunc", typeof(CompValuInline)); | ||
936 | s2t.Add("int", typeof(int)); | ||
937 | s2t.Add("int*", typeof(int).MakeByRefType()); | ||
938 | s2t.Add("intrlokd", typeof(System.Threading.Interlocked)); | ||
939 | s2t.Add("lslfloat", typeof(LSL_Float)); | ||
940 | s2t.Add("lslint", typeof(LSL_Integer)); | ||
941 | s2t.Add("lsllist", typeof(LSL_List)); | ||
942 | s2t.Add("lslrot", typeof(LSL_Rotation)); | ||
943 | s2t.Add("lslstr", typeof(LSL_String)); | ||
944 | s2t.Add("lslvec", typeof(LSL_Vector)); | ||
945 | s2t.Add("math", typeof(Math)); | ||
946 | s2t.Add("midround", typeof(MidpointRounding)); | ||
947 | s2t.Add("object", typeof(object)); | ||
948 | s2t.Add("object*", typeof(object).MakeByRefType()); | ||
949 | s2t.Add("object[]", typeof(object[])); | ||
950 | s2t.Add("scrbase", typeof(ScriptBaseClass)); | ||
951 | s2t.Add("scrcode", typeof(ScriptCodeGen)); | ||
952 | s2t.Add("sdtclobj", typeof(XMRSDTypeClObj)); | ||
953 | s2t.Add("string", typeof(string)); | ||
954 | s2t.Add("typecast", typeof(TypeCast)); | ||
955 | s2t.Add("undstatx", typeof(ScriptUndefinedStateException)); | ||
956 | s2t.Add("void", typeof(void)); | ||
957 | s2t.Add("xmrarray", typeof(XMR_Array)); | ||
958 | s2t.Add("xmrinst", typeof(XMRInstAbstract)); | ||
959 | |||
960 | return s2t; | ||
961 | } | ||
962 | |||
963 | private static Dictionary<Type, string> PopulateT2S() | ||
964 | { | ||
965 | Dictionary<string, Type> s2t = PopulateS2T(); | ||
966 | Dictionary<Type, string> t2s = new Dictionary<Type, string>(); | ||
967 | foreach(KeyValuePair<string, Type> kvp in s2t) | ||
968 | { | ||
969 | t2s.Add(kvp.Value, kvp.Key); | ||
970 | } | ||
971 | return t2s; | ||
972 | } | ||
973 | |||
974 | /** | ||
975 | * @brief Add to list of internally recognized types. | ||
976 | */ | ||
977 | public static void DefineInternalType(string name, Type type) | ||
978 | { | ||
979 | if(!string2Type.ContainsKey(name)) | ||
980 | { | ||
981 | string2Type.Add(name, type); | ||
982 | type2String.Add(type, name); | ||
983 | } | ||
984 | } | ||
985 | |||
986 | private string GetStrFromType(Type t) | ||
987 | { | ||
988 | string s = GetStrFromTypeWork(t); | ||
989 | return s; | ||
990 | } | ||
991 | private string GetStrFromTypeWork(Type t) | ||
992 | { | ||
993 | string s; | ||
994 | |||
995 | // internal fixed types like int and xmrarray etc | ||
996 | if(type2String.TryGetValue(t, out s)) | ||
997 | return s; | ||
998 | |||
999 | // script-defined types | ||
1000 | if(sdTypesRev.TryGetValue(t, out s)) | ||
1001 | return "sdt$" + s; | ||
1002 | |||
1003 | // inline function types | ||
1004 | s = TokenDeclSDTypeDelegate.TryGetInlineName(t); | ||
1005 | if(s != null) | ||
1006 | return s; | ||
1007 | |||
1008 | // last resort | ||
1009 | return t.AssemblyQualifiedName; | ||
1010 | } | ||
1011 | |||
1012 | private static Type GetTypeFromStr(Dictionary<string, TokenDeclSDType> sdTypes, string s) | ||
1013 | { | ||
1014 | Type t; | ||
1015 | |||
1016 | // internal fixed types like int and xmrarray etc | ||
1017 | if(string2Type.TryGetValue(s, out t)) | ||
1018 | return t; | ||
1019 | |||
1020 | // script-defined types | ||
1021 | if(s.StartsWith("sdt$")) | ||
1022 | return sdTypes[s.Substring(4)].GetSysType(); | ||
1023 | |||
1024 | // inline function types | ||
1025 | t = TokenDeclSDTypeDelegate.TryGetInlineSysType(s); | ||
1026 | if(t != null) | ||
1027 | return t; | ||
1028 | |||
1029 | // last resort | ||
1030 | return Type.GetType(s, true); | ||
1031 | } | ||
1032 | } | ||
1033 | |||
1034 | public class ScriptSrcLoc | ||
1035 | { | ||
1036 | public string file; | ||
1037 | public int line; | ||
1038 | public int posn; | ||
1039 | } | ||
1040 | } | ||