123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708 |
- /*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSimulator Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- using System;
- using System.Collections.Generic;
- using System.Reflection;
- using System.Reflection.Emit;
- using System.Text;
- using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
- using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
- using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
- using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
- using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
- using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
- using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
- /**
- * @brief Generate code for the backend API calls.
- */
- namespace OpenSim.Region.ScriptEngine.Yengine
- {
- public abstract class TokenDeclInline: TokenDeclVar
- {
- public static VarDict inlineFunctions = CreateDictionary();
- public abstract void CodeGen(ScriptCodeGen scg, Token errorAt, CompValuTemp result, CompValu[] args);
- private static HashSet<string> noCheckRuns;
- private static string[] keyReturns;
- protected bool isTaggedCallsCheckRun;
- /**
- * @brief Create a dictionary of inline backend API functions.
- */
- private static VarDict CreateDictionary()
- {
- /*
- * For those listed in noCheckRun, we just generate the call (simple computations).
- * For all others, we generate the call then a call to CheckRun().
- * note to self: a change here implies change on magic numbers to invalidate older code and
- * script state
- */
- noCheckRuns = new HashSet<string>() {
- "llBase64ToString",
- "llCSV2List",
- "llDeleteSubList",
- "llDeleteSubString",
- "llDumpList2String",
- "llEscapeURL",
- "llEuler2Rot",
- "llGetListEntryType",
- "llGetListLength",
- "llGetSubString",
- "llGetUnixTime",
- "llInsertString",
- "llList2CSV",
- "llList2Float",
- "llList2Integer",
- "llList2Key",
- "llList2Rot",
- "llList2String",
- "llList2Vector",
- "llListFindList",
- "llListInsertList",
- "llListRandomize",
- "llListReplaceList",
- "llListSort",
- "llListStatistics",
- "llMD5String",
- "llParseString2List",
- "llParseStringKeepNulls",
- "llRot2Euler",
- "llStringLength",
- "llStringToBase64",
- "llStringTrim",
- "llSubStringIndex",
- "llUnescapeURL",
- "osGetSitActiveRange",
- "osIsNotValidNumber",
- "osSlerp",
- "osApproxEquals",
- "osVecDistSquare",
- "osVecMagSquare",
- "osRound",
- "osGetLinkNumber",
- "osMax",
- "osMin",
- "osIsUUID"
- };
- /*
- * These functions really return a 'key' even though we see them as
- * returning 'string' because OpenSim has key and string as same type.
- */
- keyReturns = new string[] {
- "llAvatarOnLinkSitTarget",
- "llAvatarOnSitTarget",
- "llDetectedKey",
- "llDetectedOwner",
- "llGenerateKey",
- "llGetCreator",
- "llGetInventoryCreator",
- "llGetInventoryKey",
- "llGetKey",
- "llGetLandOwnerAt",
- "llGetLinkKey",
- "llGetNotecardLine",
- "llGetNumberOfNotecardLines",
- "llGetOwner",
- "llGetOwnerKey",
- "llGetPermissionsKey",
- "llHTTPRequest",
- "llList2Key",
- "llRequestAgentData",
- "llRequestDisplayName",
- "llRequestInventoryData",
- "llRequestSecureURL",
- "llRequestSimulatorData",
- "llRequestURL",
- "llRequestUsername",
- "llSendRemoteData",
- "llTransferLindenDollars"
- };
- VarDict ifd = new VarDict(false);
- Type[] oneDoub = new Type[] { typeof(double) };
- Type[] twoDoubs = new Type[] { typeof(double), typeof(double) };
-
- /*
- * Something weird about the code generation for these calls, so they all have their own handwritten code generators.
- */
- new TokenDeclInline_GetFreeMemory(ifd);
- new TokenDeclInline_GetUsedMemory(ifd);
- /*
- * These are all the xmr...() calls directly in XMRInstAbstract.
- * Includes the calls from ScriptBaseClass that has all the stubs
- * which convert XMRInstAbstract to the various <NAME>_Api contexts.
- */
- MethodInfo[] absmeths = typeof(XMRInstAbstract).GetMethods();
- AddInterfaceMethods(ifd, absmeths, null);
- return ifd;
- }
- /**
- * @brief Add API functions from the given interface to list of built-in functions.
- * Only functions beginning with a lower-case letter are entered, all others ignored.
- * @param ifd = internal function dictionary to add them to
- * @param ifaceMethods = list of API functions
- * @param acf = which field in XMRInstanceSuperType holds method's 'this' pointer
- */
- // this one accepts only names beginning with a lower-case letter
- public static void AddInterfaceMethods(VarDict ifd, MethodInfo[] ifaceMethods, FieldInfo acf)
- {
- List<MethodInfo> lcms = new List<MethodInfo>(ifaceMethods.Length);
- foreach(MethodInfo meth in ifaceMethods)
- {
- string name = meth.Name;
- if((name[0] >= 'a') && (name[0] <= 'z'))
- {
- lcms.Add(meth);
- }
- }
- AddInterfaceMethods(ifd, lcms.GetEnumerator(), acf);
- }
- // this one accepts all methods given to it
- public static void AddInterfaceMethods(VarDict ifd, IEnumerator<MethodInfo> ifaceMethods, FieldInfo acf)
- {
- ifd ??= inlineFunctions;
- for(ifaceMethods.Reset(); ifaceMethods.MoveNext();)
- {
- MethodInfo ifaceMethod = ifaceMethods.Current;
- try
- {
- /*
- * See if we will generate a call to CheckRun() right
- * after we generate a call to the function.
- * If function begins with xmr, assume we will not call CheckRun()
- * Otherwise, assume we will call CheckRun()
- */
- bool dcr = !(ifaceMethod.Name.StartsWith("xmr") || noCheckRuns.Contains(ifaceMethod.Name));
- /*
- * Add function to dictionary.
- */
- new TokenDeclInline_BEApi(ifd, dcr, ifaceMethod, acf);
- }
- catch
- {
- ///??? IGNORE ANY THAT FAIL - LIKE UNRECOGNIZED TYPE ???///
- ///??? and OVERLOADED NAMES ???///
- }
- }
- }
- /**
- * @brief Add an inline function definition to the dictionary.
- * @param ifd = dictionary to add inline definition to
- * @param doCheckRun = true iff the generated code or the function itself can possibly call CheckRun()
- * @param nameArgSig = inline function signature string, in form <name>(<arglsltypes>,...)
- * @param retType = return type, use TokenTypeVoid if no return value
- */
- protected TokenDeclInline(VarDict ifd,
- bool doCheckRun,
- string nameArgSig,
- TokenType retType)
- : base(null, null, null)
- {
- this.retType = retType;
- this.triviality = doCheckRun ? Triviality.complex : Triviality.trivial;
- int j = nameArgSig.IndexOf('(');
- this.name = new TokenName(null, nameArgSig.Substring(0, j++));
- this.argDecl = new TokenArgDecl(null);
- if(nameArgSig[j] != ')')
- {
- int i;
- TokenName name;
- TokenType type;
- for(i = j; nameArgSig[i] != ')'; i++)
- {
- if(nameArgSig[i] == ',')
- {
- type = TokenType.FromLSLType(null, nameArgSig.Substring(j, i - j));
- name = new TokenName(null, "arg" + this.argDecl.varDict.Count);
- this.argDecl.AddArg(type, name);
- j = i + 1;
- }
- }
- type = TokenType.FromLSLType(null, nameArgSig.Substring(j, i - j));
- name = new TokenName(null, "arg" + this.argDecl.varDict.Count);
- this.argDecl.AddArg(type, name);
- }
- this.location = new CompValuInline(this);
- if(ifd == null)
- ifd = inlineFunctions;
- ifd.AddEntry(this);
- }
- protected TokenDeclInline(VarDict ifd,
- bool doCheckRun,
- MethodInfo methInfo)
- : base(null, null, null)
- {
- isTaggedCallsCheckRun = IsTaggedCallsCheckRun(methInfo);
- name = new TokenName(null, methInfo.Name);
- retType = GetRetType(methInfo, TokenType.FromSysType(null, methInfo.ReturnType));
- argDecl = GetArgDecl(methInfo.GetParameters());
- triviality = (doCheckRun || isTaggedCallsCheckRun) ? Triviality.complex : Triviality.trivial;
- location = new CompValuInline(this);
- ifd ??= inlineFunctions;
- ifd.AddEntry(this);
- }
- private static TokenArgDecl GetArgDecl(ParameterInfo[] parameters)
- {
- TokenArgDecl argDecl = new TokenArgDecl(null);
- foreach(ParameterInfo pi in parameters)
- {
- TokenType type = TokenType.FromSysType(null, pi.ParameterType);
- TokenName name = new TokenName(null, pi.Name);
- argDecl.AddArg(type, name);
- }
- return argDecl;
- }
- /**
- * @brief The above code assumes all methods beginning with 'xmr' are trivial, ie,
- * they do not call CheckRun() and also we do not generate a CheckRun()
- * call after they return. So if an 'xmr' method does call CheckRun(), it
- * must be tagged with attribute 'xmrMethodCallsCheckRunAttribute' so we know
- * the method is not trivial. But in neither case do we emit our own call
- * to CheckRun(), the 'xmr' method must do its own. We do however set up a
- * call label before the call to the non-trivial 'xmr' method so when we are
- * restoring the call stack, the restore will call directly in to the 'xmr'
- * method without re-executing any code before the call to the 'xmr' method.
- */
- private static bool IsTaggedCallsCheckRun(MethodInfo methInfo)
- {
- return (methInfo != null) &&
- Attribute.IsDefined(methInfo, typeof(xmrMethodCallsCheckRunAttribute));
- }
- /**
- * @brief The dumbass OpenSim has key and string as the same type so non-ll
- * methods must be tagged with xmrMethodReturnsKeyAttribute if we
- * are to think they return a key type, otherwise we will think they
- * return string.
- */
- private static TokenType GetRetType(MethodInfo methInfo, TokenType retType)
- {
- if((methInfo != null) && (retType != null) && (retType is TokenTypeStr))
- {
- if(Attribute.IsDefined(methInfo, typeof(xmrMethodReturnsKeyAttribute)))
- {
- return ChangeToKeyType(retType);
- }
- string mn = methInfo.Name;
- foreach(string kr in keyReturns)
- {
- if(kr == mn)
- return ChangeToKeyType(retType);
- }
- }
- return retType;
- }
- private static TokenType ChangeToKeyType(TokenType retType)
- {
- if(retType is TokenTypeLSLString)
- {
- retType = new TokenTypeLSLKey(null);
- }
- else
- {
- retType = new TokenTypeKey(null);
- }
- return retType;
- }
- public virtual MethodInfo GetMethodInfo()
- {
- return null;
- }
- /**
- * @brief Print out a list of all the built-in functions and constants.
- */
- public delegate void WriteLine(string str);
- public static void PrintBuiltins(bool inclNoisyTag, WriteLine writeLine)
- {
- writeLine("\nBuilt-in functions:\n");
- SortedDictionary<string, TokenDeclInline> bifs = new SortedDictionary<string, TokenDeclInline>();
- foreach(TokenDeclVar bif in TokenDeclInline.inlineFunctions)
- {
- bifs.Add(bif.fullName, (TokenDeclInline)bif);
- }
- foreach(TokenDeclInline bif in bifs.Values)
- {
- char noisy = (!inclNoisyTag || !IsTaggedNoisy(bif.GetMethodInfo())) ? ' ' : (bif.retType is TokenTypeVoid) ? 'N' : 'R';
- writeLine(noisy + " " + bif.retType.ToString().PadLeft(8) + " " + bif.fullName);
- }
- if(inclNoisyTag)
- {
- writeLine("\nN - stub that writes name and arguments to stdout");
- writeLine("R - stub that writes name and arguments to stdout then reads return value from stdin");
- writeLine(" format is: function_name : return_value");
- writeLine(" example: llKey2Name:\"Kunta Kinte\"");
- }
- writeLine("\nBuilt-in constants:\n");
- SortedDictionary<string, ScriptConst> scs = new SortedDictionary<string, ScriptConst>();
- int widest = 0;
- foreach(ScriptConst sc in ScriptConst.scriptConstants.Values)
- {
- if(widest < sc.name.Length)
- widest = sc.name.Length;
- scs.Add(sc.name, sc);
- }
- foreach(ScriptConst sc in scs.Values)
- {
- writeLine(" " + sc.rVal.type.ToString().PadLeft(8) + " " + sc.name.PadRight(widest) + " = " + BuiltInConstVal(sc.rVal));
- }
- }
- public static bool IsTaggedNoisy(MethodInfo methInfo)
- {
- return (methInfo != null) && Attribute.IsDefined(methInfo, typeof(xmrMethodIsNoisyAttribute));
- }
- public static string BuiltInConstVal(CompValu rVal)
- {
- if(rVal is CompValuInteger)
- {
- int x = ((CompValuInteger)rVal).x;
- return "0x" + x.ToString("X8") + " = " + x.ToString().PadLeft(11);
- }
- if(rVal is CompValuFloat)
- return ((CompValuFloat)rVal).x.ToString();
- if(rVal is CompValuString)
- {
- StringBuilder sb = new StringBuilder();
- PrintParam(sb, ((CompValuString)rVal).x);
- return sb.ToString();
- }
- if(rVal is CompValuSField)
- {
- FieldInfo fi = ((CompValuSField)rVal).field;
- StringBuilder sb = new StringBuilder();
- PrintParam(sb, fi.GetValue(null));
- return sb.ToString();
- }
- return rVal.ToString(); // just prints the type
- }
- public static void PrintParam(StringBuilder sb, object p)
- {
- if(p == null)
- {
- sb.Append("null");
- }
- else if(p is LSL_List)
- {
- sb.Append('[');
- object[] d = ((LSL_List)p).Data;
- for(int i = 0; i < d.Length; i++)
- {
- if(i > 0)
- sb.Append(',');
- PrintParam(sb, d[i]);
- }
- sb.Append(']');
- }
- else if(p is LSL_Rotation)
- {
- LSL_Rotation r = (LSL_Rotation)p;
- sb.Append('<');
- sb.Append(r.x);
- sb.Append(',');
- sb.Append(r.y);
- sb.Append(',');
- sb.Append(r.z);
- sb.Append(',');
- sb.Append(r.s);
- sb.Append('>');
- }
- else if(p is LSL_String)
- {
- PrintParamString(sb, (string)(LSL_String)p);
- }
- else if(p is LSL_Vector)
- {
- LSL_Vector v = (LSL_Vector)p;
- sb.Append('<');
- sb.Append(v.x);
- sb.Append(',');
- sb.Append(v.y);
- sb.Append(',');
- sb.Append(v.z);
- sb.Append('>');
- }
- else if(p is string)
- {
- PrintParamString(sb, (string)p);
- }
- else
- {
- sb.Append(p.ToString());
- }
- }
- public static void PrintParamString(StringBuilder sb, string p)
- {
- sb.Append('"');
- foreach(char c in p)
- {
- if(c == '\b')
- {
- sb.Append("\\b");
- continue;
- }
- if(c == '\n')
- {
- sb.Append("\\n");
- continue;
- }
- if(c == '\r')
- {
- sb.Append("\\r");
- continue;
- }
- if(c == '\t')
- {
- sb.Append("\\t");
- continue;
- }
- if(c == '"')
- {
- sb.Append("\\\"");
- continue;
- }
- if(c == '\\')
- {
- sb.Append("\\\\");
- continue;
- }
- sb.Append(c);
- }
- sb.Append('"');
- }
- }
- /**
- * @brief Code generators...
- * @param scg = script we are generating code for
- * @param result = type/location for result (type matches function definition)
- * @param args = type/location of arguments (types match function definition)
- */
- /*
- public class TokenDeclInline_LLAbs: TokenDeclInline
- {
- public TokenDeclInline_LLAbs(VarDict ifd)
- : base(ifd, false, "llAbs(integer)", new TokenTypeInt(null)) { }
- public override void CodeGen(ScriptCodeGen scg, Token errorAt, CompValuTemp result, CompValu[] args)
- {
- ScriptMyLabel itsPosLabel = scg.ilGen.DefineLabel("llAbstemp");
- args[0].PushVal(scg, errorAt);
- scg.ilGen.Emit(errorAt, OpCodes.Dup);
- scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_0);
- scg.ilGen.Emit(errorAt, OpCodes.Bge_S, itsPosLabel);
- scg.ilGen.Emit(errorAt, OpCodes.Neg);
- scg.ilGen.MarkLabel(itsPosLabel);
- result.Pop(scg, errorAt, retType);
- }
- }
- public class TokenDeclInline_Math: TokenDeclInline
- {
- private MethodInfo methInfo;
- public TokenDeclInline_Math(VarDict ifd, string sig, string name, Type[] args)
- : base(ifd, false, sig, new TokenTypeFloat(null))
- {
- methInfo = ScriptCodeGen.GetStaticMethod(typeof(System.Math), name, args);
- }
- public override void CodeGen(ScriptCodeGen scg, Token errorAt, CompValuTemp result, CompValu[] args)
- {
- for(int i = 0; i < args.Length; i++)
- {
- args[i].PushVal(scg, errorAt, argDecl.types[i]);
- }
- scg.ilGen.Emit(errorAt, OpCodes.Call, methInfo);
- result.Pop(scg, errorAt, retType);
- }
- }
- public class TokenDeclInline_LLRound: TokenDeclInline
- {
- private static MethodInfo roundMethInfo = ScriptCodeGen.GetStaticMethod(typeof(System.Math), "Round",
- new Type[] { typeof(double), typeof(MidpointRounding) });
- public TokenDeclInline_LLRound(VarDict ifd)
- : base(ifd, false, "llRound(float)", new TokenTypeInt(null)) { }
- public override void CodeGen(ScriptCodeGen scg, Token errorAt, CompValuTemp result, CompValu[] args)
- {
- args[0].PushVal(scg, errorAt, new TokenTypeFloat(null));
- scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4, (int)System.MidpointRounding.AwayFromZero);
- scg.ilGen.Emit(errorAt, OpCodes.Call, roundMethInfo);
- result.Pop(scg, errorAt, new TokenTypeFloat(null));
- }
- }
- */
- public class TokenDeclInline_GetFreeMemory: TokenDeclInline
- {
- private static readonly MethodInfo getFreeMemMethInfo = typeof(XMRInstAbstract).GetMethod("xmrHeapLeft", new Type[] { });
- public TokenDeclInline_GetFreeMemory(VarDict ifd)
- : base(ifd, false, "llGetFreeMemory()", new TokenTypeInt(null)) { }
- // appears as llGetFreeMemory() in script source code
- // but actually calls xmrHeapLeft()
- public override void CodeGen(ScriptCodeGen scg, Token errorAt, CompValuTemp result, CompValu[] args)
- {
- scg.PushXMRInst();
- scg.ilGen.Emit(errorAt, OpCodes.Call, getFreeMemMethInfo);
- result.Pop(scg, errorAt, new TokenTypeInt(null));
- }
- }
- public class TokenDeclInline_GetUsedMemory: TokenDeclInline
- {
- private static readonly MethodInfo getUsedMemMethInfo = typeof(XMRInstAbstract).GetMethod("xmrHeapUsed", new Type[] { });
- public TokenDeclInline_GetUsedMemory(VarDict ifd)
- : base(ifd, false, "llGetUsedMemory()", new TokenTypeInt(null)) { }
- // appears as llGetUsedMemory() in script source code
- // but actually calls xmrHeapUsed()
- public override void CodeGen(ScriptCodeGen scg, Token errorAt, CompValuTemp result, CompValu[] args)
- {
- scg.PushXMRInst();
- scg.ilGen.Emit(errorAt, OpCodes.Call, getUsedMemMethInfo);
- result.Pop(scg, errorAt, new TokenTypeInt(null));
- }
- }
-
- /**
- * @brief Generate code for the usual ll...() functions.
- */
- public class TokenDeclInline_BEApi: TokenDeclInline
- {
- // private static readonly MethodInfo fixLLParcelMediaQuery = ScriptCodeGen.GetStaticMethod
- // (typeof (XMRInstAbstract), "FixLLParcelMediaQuery", new Type[] { typeof (LSL_List) });
- // private static readonly MethodInfo fixLLParcelMediaCommandList = ScriptCodeGen.GetStaticMethod
- // (typeof (XMRInstAbstract), "FixLLParcelMediaCommandList", new Type[] { typeof (LSL_List) });
- public bool doCheckRun;
- private FieldInfo apiContextField;
- private MethodInfo methInfo;
- /**
- * @brief Constructor
- * @param ifd = dictionary to add the function to
- * @param dcr = append a call to CheckRun()
- * @param methInfo = ll...() method to be called
- */
- public TokenDeclInline_BEApi(VarDict ifd, bool dcr, MethodInfo methInfo, FieldInfo acf)
- : base(ifd, dcr, methInfo)
- {
- this.methInfo = methInfo;
- doCheckRun = dcr;
- apiContextField = acf;
- }
- public override MethodInfo GetMethodInfo()
- {
- return methInfo;
- }
- /**
- * @brief Generate call to backend API function (eg llSay()) maybe followed by a call to CheckRun().
- * @param scg = script being compiled
- * @param result = where to place result (might be void)
- * @param args = script-visible arguments to pass to API function
- */
- public override void CodeGen(ScriptCodeGen scg, Token errorAt, CompValuTemp result, CompValu[] args)
- {
- if(isTaggedCallsCheckRun)
- { // see if 'xmr' method that calls CheckRun() internally
- new ScriptCodeGen.CallLabel(scg, errorAt); // if so, put a call label immediately before it
- // .. so restoring the frame will jump immediately to the
- // .. call without re-executing any code before this
- }
- if(!methInfo.IsStatic)
- {
- scg.PushXMRInst(); // XMRInstanceSuperType pointer
- if(apiContextField != null) // 'this' pointer for API function
- scg.ilGen.Emit(errorAt, OpCodes.Ldfld, apiContextField);
- }
- for(int i = 0; i < args.Length; i++) // push arguments, boxing/unboxing as needed
- args[i].PushVal(scg, errorAt, argDecl.types[i]);
- // this should not be needed
- // if (methInfo.Name == "llParcelMediaQuery") {
- // scg.ilGen.Emit (errorAt, OpCodes.Call, fixLLParcelMediaQuery);
- // }
- // this should not be needed
- // if (methInfo.Name == "llParcelMediaCommandList") {
- // scg.ilGen.Emit (errorAt, OpCodes.Call, fixLLParcelMediaCommandList);
- // }
- if(methInfo.IsVirtual) // call API function
- scg.ilGen.Emit(errorAt, OpCodes.Callvirt, methInfo);
- else
- scg.ilGen.Emit(errorAt, OpCodes.Call, methInfo);
- result.Pop(scg, errorAt, retType); // pop result, boxing/unboxing as needed
- if(isTaggedCallsCheckRun)
- scg.openCallLabel = null;
- if(doCheckRun)
- scg.EmitCallCheckRun(errorAt, false); // maybe call CheckRun()
- }
- }
- }
|