aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/XMREngine/MMRScriptInlines.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ScriptEngine/XMREngine/MMRScriptInlines.cs666
1 files changed, 0 insertions, 666 deletions
diff --git a/OpenSim/Region/ScriptEngine/XMREngine/MMRScriptInlines.cs b/OpenSim/Region/ScriptEngine/XMREngine/MMRScriptInlines.cs
deleted file mode 100644
index fcb4b66..0000000
--- a/OpenSim/Region/ScriptEngine/XMREngine/MMRScriptInlines.cs
+++ /dev/null
@@ -1,666 +0,0 @@
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
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Reflection.Emit;
32using System.Text;
33
34using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
35using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
36using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
37using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
38using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
39using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
40using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
41
42/**
43 * @brief Generate code for the backend API calls.
44 */
45namespace OpenSim.Region.ScriptEngine.XMREngine
46{
47 public abstract class TokenDeclInline : TokenDeclVar {
48 public static VarDict inlineFunctions = CreateDictionary ();
49
50 public abstract void CodeGen (ScriptCodeGen scg, Token errorAt, CompValuTemp result, CompValu[] args);
51
52 private static string[] noCheckRuns;
53 private static string[] keyReturns;
54
55 protected bool isTaggedCallsCheckRun;
56
57 /**
58 * @brief Create a dictionary of inline backend API functions.
59 */
60 private static VarDict CreateDictionary ()
61 {
62 /*
63 * For those listed in noCheckRun, we just generate the call (simple computations).
64 * For all others, we generate the call then a call to CheckRun().
65 */
66 noCheckRuns = new string[] {
67 "llBase64ToString",
68 "llCSV2List",
69 "llDeleteSubList",
70 "llDeleteSubString",
71 "llDumpList2String",
72 "llEscapeURL",
73 "llEuler2Rot",
74 "llGetListEntryType",
75 "llGetListLength",
76 "llGetSubString",
77 "llGetUnixTime",
78 "llInsertString",
79 "llList2CSV",
80 "llList2Float",
81 "llList2Integer",
82 "llList2Key",
83 "llList2List",
84 "llList2ListStrided",
85 "llList2Rot",
86 "llList2String",
87 "llList2Vector",
88 "llListFindList",
89 "llListInsertList",
90 "llListRandomize",
91 "llListReplaceList",
92 "llListSort",
93 "llListStatistics",
94 "llMD5String",
95 "llParseString2List",
96 "llParseStringKeepNulls",
97 "llRot2Euler",
98 "llStringLength",
99 "llStringToBase64",
100 "llStringTrim",
101 "llSubStringIndex",
102 "llUnescapeURL"
103 };
104
105 /*
106 * These functions really return a 'key' even though we see them as
107 * returning 'string' because OpenSim has key and string as same type.
108 */
109 keyReturns = new string[] {
110 "llAvatarOnLinkSitTarget",
111 "llAvatarOnSitTarget",
112 "llDetectedKey",
113 "llDetectedOwner",
114 "llGenerateKey",
115 "llGetCreator",
116 "llGetInventoryCreator",
117 "llGetInventoryKey",
118 "llGetKey",
119 "llGetLandOwnerAt",
120 "llGetLinkKey",
121 "llGetNotecardLine",
122 "llGetNumberOfNotecardLines",
123 "llGetOwner",
124 "llGetOwnerKey",
125 "llGetPermissionsKey",
126 "llHTTPRequest",
127 "llList2Key",
128 "llRequestAgentData",
129 "llRequestDisplayName",
130 "llRequestInventoryData",
131 "llRequestSecureURL",
132 "llRequestSimulatorData",
133 "llRequestURL",
134 "llRequestUsername",
135 "llSendRemoteData",
136 "llTransferLindenDollars"
137 };
138
139 VarDict ifd = new VarDict (false);
140
141 Type[] oneDoub = new Type[] { typeof (double) };
142 Type[] twoDoubs = new Type[] { typeof (double), typeof (double) };
143
144 /*
145 * Mono generates an FPU instruction for many math calls.
146 */
147 new TokenDeclInline_LLAbs (ifd);
148 new TokenDeclInline_Math (ifd, "llAcos(float)", "Acos", oneDoub);
149 new TokenDeclInline_Math (ifd, "llAsin(float)", "Asin", oneDoub);
150 new TokenDeclInline_Math (ifd, "llAtan2(float,float)", "Atan2", twoDoubs);
151 new TokenDeclInline_Math (ifd, "llCos(float)", "Cos", oneDoub);
152 new TokenDeclInline_Math (ifd, "llFabs(float)", "Abs", oneDoub);
153 new TokenDeclInline_Math (ifd, "llLog(float)", "Log", oneDoub);
154 new TokenDeclInline_Math (ifd, "llLog10(float)", "Log10", oneDoub);
155 new TokenDeclInline_Math (ifd, "llPow(float,float)", "Pow", twoDoubs);
156 new TokenDeclInline_LLRound (ifd);
157 new TokenDeclInline_Math (ifd, "llSin(float)", "Sin", oneDoub);
158 new TokenDeclInline_Math (ifd, "llSqrt(float)", "Sqrt", oneDoub);
159 new TokenDeclInline_Math (ifd, "llTan(float)", "Tan", oneDoub);
160
161 /*
162 * Something weird about the code generation for these calls, so they all have their own handwritten code generators.
163 */
164 new TokenDeclInline_GetFreeMemory (ifd);
165 new TokenDeclInline_GetUsedMemory (ifd);
166
167 /*
168 * These are all the xmr...() calls directly in XMRInstAbstract.
169 * Includes the calls from ScriptBaseClass that has all the stubs
170 * which convert XMRInstAbstract to the various <NAME>_Api contexts.
171 */
172 MethodInfo[] absmeths = typeof (XMRInstAbstract).GetMethods ();
173 AddInterfaceMethods (ifd, absmeths, null);
174
175 return ifd;
176 }
177
178 /**
179 * @brief Add API functions from the given interface to list of built-in functions.
180 * Only functions beginning with a lower-case letter are entered, all others ignored.
181 * @param ifd = internal function dictionary to add them to
182 * @param ifaceMethods = list of API functions
183 * @param acf = which field in XMRInstanceSuperType holds method's 'this' pointer
184 */
185 // this one accepts only names beginning with a lower-case letter
186 public static void AddInterfaceMethods (VarDict ifd, MethodInfo[] ifaceMethods, FieldInfo acf)
187 {
188 List<MethodInfo> lcms = new List<MethodInfo> (ifaceMethods.Length);
189 foreach (MethodInfo meth in ifaceMethods)
190 {
191 string name = meth.Name;
192 if ((name[0] >= 'a') && (name[0] <= 'z')) {
193 lcms.Add (meth);
194 }
195 }
196 AddInterfaceMethods (ifd, lcms.GetEnumerator (), acf);
197 }
198
199 // this one accepts all methods given to it
200 public static void AddInterfaceMethods (VarDict ifd, IEnumerator<MethodInfo> ifaceMethods, FieldInfo acf)
201 {
202 if (ifd == null) ifd = inlineFunctions;
203
204 for (ifaceMethods.Reset (); ifaceMethods.MoveNext ();) {
205 MethodInfo ifaceMethod = ifaceMethods.Current;
206 string key = ifaceMethod.Name;
207
208 try {
209 /*
210 * See if we will generate a call to CheckRun() right
211 * after we generate a call to the function.
212 * If function begins with xmr, assume we will not call CheckRun()
213 * Otherwise, assume we will call CheckRun()
214 */
215 bool dcr = !key.StartsWith ("xmr");
216 foreach (string ncr in noCheckRuns) {
217 if (ncr == key) {
218 dcr = false;
219 break;
220 }
221 }
222
223 /*
224 * Add function to dictionary.
225 */
226 new TokenDeclInline_BEApi (ifd, dcr, ifaceMethod, acf);
227 } catch {
228 ///??? IGNORE ANY THAT FAIL - LIKE UNRECOGNIZED TYPE ???///
229 ///??? and OVERLOADED NAMES ???///
230 }
231 }
232 }
233
234 /**
235 * @brief Add an inline function definition to the dictionary.
236 * @param ifd = dictionary to add inline definition to
237 * @param doCheckRun = true iff the generated code or the function itself can possibly call CheckRun()
238 * @param nameArgSig = inline function signature string, in form <name>(<arglsltypes>,...)
239 * @param retType = return type, use TokenTypeVoid if no return value
240 */
241 protected TokenDeclInline (VarDict ifd,
242 bool doCheckRun,
243 string nameArgSig,
244 TokenType retType)
245 : base (null, null, null)
246 {
247 this.retType = retType;
248 this.triviality = doCheckRun ? Triviality.complex : Triviality.trivial;
249
250 int j = nameArgSig.IndexOf ('(');
251 this.name = new TokenName (null, nameArgSig.Substring (0, j ++));
252
253 this.argDecl = new TokenArgDecl (null);
254 if (nameArgSig[j] != ')') {
255 int i;
256 TokenName name;
257 TokenType type;
258
259 for (i = j; nameArgSig[i] != ')'; i ++) {
260 if (nameArgSig[i] == ',') {
261 type = TokenType.FromLSLType (null, nameArgSig.Substring (j, i - j));
262 name = new TokenName (null, "arg" + this.argDecl.varDict.Count);
263 this.argDecl.AddArg (type, name);
264 j = i + 1;
265 }
266 }
267
268 type = TokenType.FromLSLType (null, nameArgSig.Substring (j, i - j));
269 name = new TokenName (null, "arg" + this.argDecl.varDict.Count);
270 this.argDecl.AddArg (type, name);
271 }
272
273 this.location = new CompValuInline (this);
274 if (ifd == null) ifd = inlineFunctions;
275 ifd.AddEntry (this);
276 }
277
278 protected TokenDeclInline (VarDict ifd,
279 bool doCheckRun,
280 MethodInfo methInfo)
281 : base (null, null, null)
282 {
283 TokenType retType = TokenType.FromSysType (null, methInfo.ReturnType);
284
285 this.isTaggedCallsCheckRun = IsTaggedCallsCheckRun (methInfo);
286 this.name = new TokenName (null, methInfo.Name);
287 this.retType = GetRetType (methInfo, retType);
288 this.argDecl = GetArgDecl (methInfo.GetParameters ());
289 this.triviality = (doCheckRun || this.isTaggedCallsCheckRun) ? Triviality.complex : Triviality.trivial;
290 this.location = new CompValuInline (this);
291
292 if (ifd == null) ifd = inlineFunctions;
293 ifd.AddEntry (this);
294 }
295
296 private static TokenArgDecl GetArgDecl (ParameterInfo[] parameters)
297 {
298 TokenArgDecl argDecl = new TokenArgDecl (null);
299 foreach (ParameterInfo pi in parameters) {
300 TokenType type = TokenType.FromSysType (null, pi.ParameterType);
301 TokenName name = new TokenName (null, pi.Name);
302 argDecl.AddArg (type, name);
303 }
304 return argDecl;
305 }
306
307 /**
308 * @brief The above code assumes all methods beginning with 'xmr' are trivial, ie,
309 * they do not call CheckRun() and also we do not generate a CheckRun()
310 * call after they return. So if an 'xmr' method does call CheckRun(), it
311 * must be tagged with attribute 'xmrMethodCallsCheckRunAttribute' so we know
312 * the method is not trivial. But in neither case do we emit our own call
313 * to CheckRun(), the 'xmr' method must do its own. We do however set up a
314 * call label before the call to the non-trivial 'xmr' method so when we are
315 * restoring the call stack, the restore will call directly in to the 'xmr'
316 * method without re-executing any code before the call to the 'xmr' method.
317 */
318 private static bool IsTaggedCallsCheckRun (MethodInfo methInfo)
319 {
320 return (methInfo != null) &&
321 Attribute.IsDefined (methInfo, typeof (xmrMethodCallsCheckRunAttribute));
322 }
323
324 /**
325 * @brief The dumbass OpenSim has key and string as the same type so non-ll
326 * methods must be tagged with xmrMethodReturnsKeyAttribute if we
327 * are to think they return a key type, otherwise we will think they
328 * return string.
329 */
330 private static TokenType GetRetType (MethodInfo methInfo, TokenType retType)
331 {
332 if ((methInfo != null) && (retType != null) && (retType is TokenTypeStr)) {
333 if (Attribute.IsDefined (methInfo, typeof (xmrMethodReturnsKeyAttribute))) {
334 return ChangeToKeyType (retType);
335 }
336
337 string mn = methInfo.Name;
338 foreach (string kr in keyReturns) {
339 if (kr == mn) return ChangeToKeyType (retType);
340 }
341
342 }
343 return retType;
344 }
345 private static TokenType ChangeToKeyType (TokenType retType)
346 {
347 if (retType is TokenTypeLSLString) {
348 retType = new TokenTypeLSLKey (null);
349 } else {
350 retType = new TokenTypeKey (null);
351 }
352 return retType;
353 }
354
355 public virtual MethodInfo GetMethodInfo ()
356 {
357 return null;
358 }
359
360 /**
361 * @brief Print out a list of all the built-in functions and constants.
362 */
363 public delegate void WriteLine (string str);
364 public static void PrintBuiltins (bool inclNoisyTag, WriteLine writeLine)
365 {
366 writeLine ("\nBuilt-in functions:\n");
367 SortedDictionary<string, TokenDeclInline> bifs = new SortedDictionary<string, TokenDeclInline> ();
368 foreach (TokenDeclVar bif in TokenDeclInline.inlineFunctions) {
369 bifs.Add (bif.fullName, (TokenDeclInline)bif);
370 }
371 foreach (TokenDeclInline bif in bifs.Values) {
372 char noisy = (!inclNoisyTag || !IsTaggedNoisy (bif.GetMethodInfo ())) ? ' ' : (bif.retType is TokenTypeVoid) ? 'N' : 'R';
373 writeLine (noisy + " " + bif.retType.ToString ().PadLeft (8) + " " + bif.fullName);
374 }
375 if (inclNoisyTag) {
376 writeLine ("\nN - stub that writes name and arguments to stdout");
377 writeLine ("R - stub that writes name and arguments to stdout then reads return value from stdin");
378 writeLine (" format is: function_name : return_value");
379 writeLine (" example: llKey2Name:\"Kunta Kinte\"");
380 }
381
382 writeLine ("\nBuilt-in constants:\n");
383 SortedDictionary<string, ScriptConst> scs = new SortedDictionary<string, ScriptConst> ();
384 int widest = 0;
385 foreach (ScriptConst sc in ScriptConst.scriptConstants.Values) {
386 if (widest < sc.name.Length) widest = sc.name.Length;
387 scs.Add (sc.name, sc);
388 }
389 foreach (ScriptConst sc in scs.Values) {
390 writeLine (" " + sc.rVal.type.ToString ().PadLeft (8) + " " + sc.name.PadRight (widest) + " = " + BuiltInConstVal (sc.rVal));
391 }
392 }
393
394 public static bool IsTaggedNoisy (MethodInfo methInfo)
395 {
396 return (methInfo != null) && Attribute.IsDefined (methInfo, typeof (xmrMethodIsNoisyAttribute));
397 }
398
399 public static string BuiltInConstVal (CompValu rVal)
400 {
401 if (rVal is CompValuInteger) {
402 int x = ((CompValuInteger)rVal).x;
403 return "0x" + x.ToString ("X8") + " = " + x.ToString ().PadLeft (11);
404 }
405 if (rVal is CompValuFloat) return ((CompValuFloat)rVal).x.ToString ();
406 if (rVal is CompValuString) {
407 StringBuilder sb = new StringBuilder ();
408 PrintParam (sb, ((CompValuString)rVal).x);
409 return sb.ToString ();
410 }
411 if (rVal is CompValuSField) {
412 FieldInfo fi = ((CompValuSField)rVal).field;
413 StringBuilder sb = new StringBuilder ();
414 PrintParam (sb, fi.GetValue (null));
415 return sb.ToString ();
416 }
417 return rVal.ToString (); // just prints the type
418 }
419
420 public static void PrintParam (StringBuilder sb, object p)
421 {
422 if (p == null) {
423 sb.Append ("null");
424 } else if (p is LSL_List) {
425 sb.Append ('[');
426 object[] d = ((LSL_List)p).Data;
427 for (int i = 0; i < d.Length; i ++) {
428 if (i > 0) sb.Append (',');
429 PrintParam (sb, d[i]);
430 }
431 sb.Append (']');
432 } else if (p is LSL_Rotation) {
433 LSL_Rotation r = (LSL_Rotation)p;
434 sb.Append ('<');
435 sb.Append (r.x);
436 sb.Append (',');
437 sb.Append (r.y);
438 sb.Append (',');
439 sb.Append (r.z);
440 sb.Append (',');
441 sb.Append (r.s);
442 sb.Append ('>');
443 } else if (p is LSL_String) {
444 PrintParamString (sb, (string)(LSL_String)p);
445 } else if (p is LSL_Vector) {
446 LSL_Vector v = (LSL_Vector)p;
447 sb.Append ('<');
448 sb.Append (v.x);
449 sb.Append (',');
450 sb.Append (v.y);
451 sb.Append (',');
452 sb.Append (v.z);
453 sb.Append ('>');
454 } else if (p is string) {
455 PrintParamString (sb, (string)p);
456 } else {
457 sb.Append (p.ToString ());
458 }
459 }
460
461 public static void PrintParamString (StringBuilder sb, string p)
462 {
463 sb.Append ('"');
464 foreach (char c in p) {
465 if (c == '\b') {
466 sb.Append ("\\b");
467 continue;
468 }
469 if (c == '\n') {
470 sb.Append ("\\n");
471 continue;
472 }
473 if (c == '\r') {
474 sb.Append ("\\r");
475 continue;
476 }
477 if (c == '\t') {
478 sb.Append ("\\t");
479 continue;
480 }
481 if (c == '"') {
482 sb.Append ("\\\"");
483 continue;
484 }
485 if (c == '\\') {
486 sb.Append ("\\\\");
487 continue;
488 }
489 sb.Append (c);
490 }
491 sb.Append ('"');
492 }
493 }
494
495 /**
496 * @brief Code generators...
497 * @param scg = script we are generating code for
498 * @param result = type/location for result (type matches function definition)
499 * @param args = type/location of arguments (types match function definition)
500 */
501
502 public class TokenDeclInline_LLAbs : TokenDeclInline {
503 public TokenDeclInline_LLAbs (VarDict ifd)
504 : base (ifd, false, "llAbs(integer)", new TokenTypeInt (null)) { }
505
506 public override void CodeGen (ScriptCodeGen scg, Token errorAt, CompValuTemp result, CompValu[] args)
507 {
508 ScriptMyLabel itsPosLabel = scg.ilGen.DefineLabel ("llAbstemp");
509
510 args[0].PushVal (scg, errorAt);
511 scg.ilGen.Emit (errorAt, OpCodes.Dup);
512 scg.ilGen.Emit (errorAt, OpCodes.Ldc_I4_0);
513 scg.ilGen.Emit (errorAt, OpCodes.Bge_S, itsPosLabel);
514 scg.ilGen.Emit (errorAt, OpCodes.Neg);
515 scg.ilGen.MarkLabel (itsPosLabel);
516 result.Pop (scg, errorAt, retType);
517 }
518 }
519
520 public class TokenDeclInline_Math : TokenDeclInline {
521 private MethodInfo methInfo;
522
523 public TokenDeclInline_Math (VarDict ifd, string sig, string name, Type[] args)
524 : base (ifd, false, sig, new TokenTypeFloat (null))
525 {
526 methInfo = ScriptCodeGen.GetStaticMethod (typeof (System.Math), name, args);
527 }
528
529 public override void CodeGen (ScriptCodeGen scg, Token errorAt, CompValuTemp result, CompValu[] args)
530 {
531 for (int i = 0; i < args.Length; i ++) {
532 args[i].PushVal (scg, errorAt, argDecl.types[i]);
533 }
534 scg.ilGen.Emit (errorAt, OpCodes.Call, methInfo);
535 result.Pop (scg, errorAt, retType);
536 }
537 }
538
539 public class TokenDeclInline_LLRound : TokenDeclInline {
540
541 private static MethodInfo roundMethInfo = ScriptCodeGen.GetStaticMethod (typeof (System.Math), "Round",
542 new Type[] { typeof (double), typeof (MidpointRounding) });
543
544 public TokenDeclInline_LLRound (VarDict ifd)
545 : base (ifd, false, "llRound(float)", new TokenTypeInt (null)) { }
546
547 public override void CodeGen (ScriptCodeGen scg, Token errorAt, CompValuTemp result, CompValu[] args)
548 {
549 args[0].PushVal (scg, errorAt, new TokenTypeFloat (null));
550 scg.ilGen.Emit (errorAt, OpCodes.Ldc_I4, (int)System.MidpointRounding.AwayFromZero);
551 scg.ilGen.Emit (errorAt, OpCodes.Call, roundMethInfo);
552 result.Pop (scg, errorAt, new TokenTypeFloat (null));
553 }
554 }
555
556 public class TokenDeclInline_GetFreeMemory : TokenDeclInline {
557 private static readonly MethodInfo getFreeMemMethInfo = typeof (XMRInstAbstract).GetMethod ("xmrHeapLeft", new Type[] { });
558
559 public TokenDeclInline_GetFreeMemory (VarDict ifd)
560 : base (ifd, false, "llGetFreeMemory()", new TokenTypeInt (null)) { }
561
562 // appears as llGetFreeMemory() in script source code
563 // but actually calls xmrHeapLeft()
564 public override void CodeGen (ScriptCodeGen scg, Token errorAt, CompValuTemp result, CompValu[] args)
565 {
566 scg.PushXMRInst ();
567 scg.ilGen.Emit (errorAt, OpCodes.Call, getFreeMemMethInfo);
568 result.Pop (scg, errorAt, new TokenTypeInt (null));
569 }
570 }
571
572 public class TokenDeclInline_GetUsedMemory : TokenDeclInline {
573 private static readonly MethodInfo getUsedMemMethInfo = typeof (XMRInstAbstract).GetMethod ("xmrHeapUsed", new Type[] { });
574
575 public TokenDeclInline_GetUsedMemory (VarDict ifd)
576 : base (ifd, false, "llGetUsedMemory()", new TokenTypeInt (null)) { }
577
578 // appears as llGetUsedMemory() in script source code
579 // but actually calls xmrHeapUsed()
580 public override void CodeGen (ScriptCodeGen scg, Token errorAt, CompValuTemp result, CompValu[] args)
581 {
582 scg.PushXMRInst ();
583 scg.ilGen.Emit (errorAt, OpCodes.Call, getUsedMemMethInfo);
584 result.Pop (scg, errorAt, new TokenTypeInt (null));
585 }
586 }
587
588 /**
589 * @brief Generate code for the usual ll...() functions.
590 */
591 public class TokenDeclInline_BEApi : TokenDeclInline {
592// private static readonly MethodInfo fixLLParcelMediaQuery = ScriptCodeGen.GetStaticMethod
593// (typeof (XMRInstAbstract), "FixLLParcelMediaQuery", new Type[] { typeof (LSL_List) });
594
595// private static readonly MethodInfo fixLLParcelMediaCommandList = ScriptCodeGen.GetStaticMethod
596// (typeof (XMRInstAbstract), "FixLLParcelMediaCommandList", new Type[] { typeof (LSL_List) });
597
598 public bool doCheckRun;
599 private FieldInfo apiContextField;
600 private MethodInfo methInfo;
601
602 /**
603 * @brief Constructor
604 * @param ifd = dictionary to add the function to
605 * @param dcr = append a call to CheckRun()
606 * @param methInfo = ll...() method to be called
607 */
608 public TokenDeclInline_BEApi (VarDict ifd, bool dcr, MethodInfo methInfo, FieldInfo acf)
609 : base (ifd, dcr, methInfo)
610 {
611 this.methInfo = methInfo;
612 doCheckRun = dcr;
613 apiContextField = acf;
614 }
615
616 public override MethodInfo GetMethodInfo ()
617 {
618 return methInfo;
619 }
620
621 /**
622 * @brief Generate call to backend API function (eg llSay()) maybe followed by a call to CheckRun().
623 * @param scg = script being compiled
624 * @param result = where to place result (might be void)
625 * @param args = script-visible arguments to pass to API function
626 */
627 public override void CodeGen (ScriptCodeGen scg, Token errorAt, CompValuTemp result, CompValu[] args)
628 {
629 if (isTaggedCallsCheckRun)
630 { // see if 'xmr' method that calls CheckRun() internally
631 new ScriptCodeGen.CallLabel (scg, errorAt); // if so, put a call label immediately before it
632 // .. so restoring the frame will jump immediately to the
633 // .. call without re-executing any code before this
634 }
635 if (!methInfo.IsStatic)
636 {
637 scg.PushXMRInst (); // XMRInstanceSuperType pointer
638 if (apiContextField != null) // 'this' pointer for API function
639 scg.ilGen.Emit (errorAt, OpCodes.Ldfld, apiContextField);
640
641 }
642 for (int i = 0; i < args.Length; i ++) // push arguments, boxing/unboxing as needed
643 args[i].PushVal (scg, errorAt, argDecl.types[i]);
644
645 // this should not be needed
646// if (methInfo.Name == "llParcelMediaQuery") {
647// scg.ilGen.Emit (errorAt, OpCodes.Call, fixLLParcelMediaQuery);
648// }
649 // this should not be needed
650// if (methInfo.Name == "llParcelMediaCommandList") {
651// scg.ilGen.Emit (errorAt, OpCodes.Call, fixLLParcelMediaCommandList);
652// }
653 if (methInfo.IsVirtual) // call API function
654 scg.ilGen.Emit (errorAt, OpCodes.Callvirt, methInfo);
655 else
656 scg.ilGen.Emit (errorAt, OpCodes.Call, methInfo);
657
658 result.Pop (scg, errorAt, retType); // pop result, boxing/unboxing as needed
659 if (isTaggedCallsCheckRun)
660 scg.openCallLabel = null;
661
662 if (doCheckRun)
663 scg.EmitCallCheckRun (errorAt, false); // maybe call CheckRun()
664 }
665 }
666}