From 2129d941acbc5f83aca4dc4c30a62d3226888136 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 23 Feb 2018 14:52:34 +0000 Subject: 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 --- .../ScriptEngine/YEngine/MMRScriptBinOpStr.cs | 1569 ++++++++++++++++++++ 1 file changed, 1569 insertions(+) create mode 100644 OpenSim/Region/ScriptEngine/YEngine/MMRScriptBinOpStr.cs (limited to 'OpenSim/Region/ScriptEngine/YEngine/MMRScriptBinOpStr.cs') diff --git a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptBinOpStr.cs b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptBinOpStr.cs new file mode 100644 index 0000000..0d6d4bd --- /dev/null +++ b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptBinOpStr.cs @@ -0,0 +1,1569 @@ +/* + * 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 OpenSim.Region.ScriptEngine.Shared.ScriptBase; +using OpenSim.Region.ScriptEngine.Yengine; +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; +using System.Text.RegularExpressions; + +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; + +namespace OpenSim.Region.ScriptEngine.Yengine +{ + + /** + * @brief This class is used to catalog the code emit routines based on a key string + * The key string has the two types (eg, "integer", "rotation") and the operator (eg, "*", "!=") + */ + public delegate void BinOpStrEmitBO(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result); + public class BinOpStr + { + public static readonly Dictionary defined = DefineBinOps(); + + public Type outtype; // type of result of computation + public BinOpStrEmitBO emitBO; // how to compute result + public bool rmwOK; // is the = form valid? + + public BinOpStr(Type outtype, BinOpStrEmitBO emitBO) + { + this.outtype = outtype; + this.emitBO = emitBO; + this.rmwOK = false; + } + + public BinOpStr(Type outtype, BinOpStrEmitBO emitBO, bool rmwOK) + { + this.outtype = outtype; + this.emitBO = emitBO; + this.rmwOK = rmwOK; + } + + private static TokenTypeBool tokenTypeBool = new TokenTypeBool(null); + private static TokenTypeChar tokenTypeChar = new TokenTypeChar(null); + private static TokenTypeFloat tokenTypeFloat = new TokenTypeFloat(null); + private static TokenTypeInt tokenTypeInt = new TokenTypeInt(null); + private static TokenTypeList tokenTypeList = new TokenTypeList(null); + private static TokenTypeRot tokenTypeRot = new TokenTypeRot(null); + private static TokenTypeStr tokenTypeStr = new TokenTypeStr(null); + private static TokenTypeVec tokenTypeVec = new TokenTypeVec(null); + + private static MethodInfo stringAddStringMethInfo = ScriptCodeGen.GetStaticMethod(typeof(string), "Concat", new Type[] { typeof(string), typeof(string) }); + private static MethodInfo stringCmpStringMethInfo = ScriptCodeGen.GetStaticMethod(typeof(string), "Compare", new Type[] { typeof(string), typeof(string) }); + + private static MethodInfo infoMethListAddFloat = GetBinOpsMethod("MethListAddFloat", new Type[] { typeof(LSL_List), typeof(double) }); + private static MethodInfo infoMethListAddInt = GetBinOpsMethod("MethListAddInt", new Type[] { typeof(LSL_List), typeof(int) }); + private static MethodInfo infoMethListAddKey = GetBinOpsMethod("MethListAddKey", new Type[] { typeof(LSL_List), typeof(string) }); + private static MethodInfo infoMethListAddRot = GetBinOpsMethod("MethListAddRot", new Type[] { typeof(LSL_List), typeof(LSL_Rotation) }); + private static MethodInfo infoMethListAddStr = GetBinOpsMethod("MethListAddStr", new Type[] { typeof(LSL_List), typeof(string) }); + private static MethodInfo infoMethListAddVec = GetBinOpsMethod("MethListAddVec", new Type[] { typeof(LSL_List), typeof(LSL_Vector) }); + private static MethodInfo infoMethListAddList = GetBinOpsMethod("MethListAddList", new Type[] { typeof(LSL_List), typeof(LSL_List) }); + private static MethodInfo infoMethFloatAddList = GetBinOpsMethod("MethFloatAddList", new Type[] { typeof(double), typeof(LSL_List) }); + private static MethodInfo infoMethIntAddList = GetBinOpsMethod("MethIntAddList", new Type[] { typeof(int), typeof(LSL_List) }); + private static MethodInfo infoMethKeyAddList = GetBinOpsMethod("MethKeyAddList", new Type[] { typeof(string), typeof(LSL_List) }); + private static MethodInfo infoMethRotAddList = GetBinOpsMethod("MethRotAddList", new Type[] { typeof(LSL_Rotation), typeof(LSL_List) }); + private static MethodInfo infoMethStrAddList = GetBinOpsMethod("MethStrAddList", new Type[] { typeof(string), typeof(LSL_List) }); + private static MethodInfo infoMethVecAddList = GetBinOpsMethod("MethVecAddList", new Type[] { typeof(LSL_Vector), typeof(LSL_List) }); + private static MethodInfo infoMethListEqList = GetBinOpsMethod("MethListEqList", new Type[] { typeof(LSL_List), typeof(LSL_List) }); + private static MethodInfo infoMethListNeList = GetBinOpsMethod("MethListNeList", new Type[] { typeof(LSL_List), typeof(LSL_List) }); + private static MethodInfo infoMethRotEqRot = GetBinOpsMethod("MethRotEqRot", new Type[] { typeof(LSL_Rotation), typeof(LSL_Rotation) }); + private static MethodInfo infoMethRotNeRot = GetBinOpsMethod("MethRotNeRot", new Type[] { typeof(LSL_Rotation), typeof(LSL_Rotation) }); + private static MethodInfo infoMethRotAddRot = GetBinOpsMethod("MethRotAddRot", new Type[] { typeof(LSL_Rotation), typeof(LSL_Rotation) }); + private static MethodInfo infoMethRotSubRot = GetBinOpsMethod("MethRotSubRot", new Type[] { typeof(LSL_Rotation), typeof(LSL_Rotation) }); + private static MethodInfo infoMethRotMulRot = GetBinOpsMethod("MethRotMulRot", new Type[] { typeof(LSL_Rotation), typeof(LSL_Rotation) }); + private static MethodInfo infoMethRotDivRot = GetBinOpsMethod("MethRotDivRot", new Type[] { typeof(LSL_Rotation), typeof(LSL_Rotation) }); + private static MethodInfo infoMethVecEqVec = GetBinOpsMethod("MethVecEqVec", new Type[] { typeof(LSL_Vector), typeof(LSL_Vector) }); + private static MethodInfo infoMethVecNeVec = GetBinOpsMethod("MethVecNeVec", new Type[] { typeof(LSL_Vector), typeof(LSL_Vector) }); + private static MethodInfo infoMethVecAddVec = GetBinOpsMethod("MethVecAddVec", new Type[] { typeof(LSL_Vector), typeof(LSL_Vector) }); + private static MethodInfo infoMethVecSubVec = GetBinOpsMethod("MethVecSubVec", new Type[] { typeof(LSL_Vector), typeof(LSL_Vector) }); + private static MethodInfo infoMethVecMulVec = GetBinOpsMethod("MethVecMulVec", new Type[] { typeof(LSL_Vector), typeof(LSL_Vector) }); + private static MethodInfo infoMethVecModVec = GetBinOpsMethod("MethVecModVec", new Type[] { typeof(LSL_Vector), typeof(LSL_Vector) }); + private static MethodInfo infoMethVecMulFloat = GetBinOpsMethod("MethVecMulFloat", new Type[] { typeof(LSL_Vector), typeof(double) }); + private static MethodInfo infoMethFloatMulVec = GetBinOpsMethod("MethFloatMulVec", new Type[] { typeof(double), typeof(LSL_Vector) }); + private static MethodInfo infoMethVecDivFloat = GetBinOpsMethod("MethVecDivFloat", new Type[] { typeof(LSL_Vector), typeof(double) }); + private static MethodInfo infoMethVecMulInt = GetBinOpsMethod("MethVecMulInt", new Type[] { typeof(LSL_Vector), typeof(int) }); + private static MethodInfo infoMethIntMulVec = GetBinOpsMethod("MethIntMulVec", new Type[] { typeof(int), typeof(LSL_Vector) }); + private static MethodInfo infoMethVecDivInt = GetBinOpsMethod("MethVecDivInt", new Type[] { typeof(LSL_Vector), typeof(int) }); + private static MethodInfo infoMethVecMulRot = GetBinOpsMethod("MethVecMulRot", new Type[] { typeof(LSL_Vector), typeof(LSL_Rotation) }); + private static MethodInfo infoMethVecDivRot = GetBinOpsMethod("MethVecDivRot", new Type[] { typeof(LSL_Vector), typeof(LSL_Rotation) }); + + private static MethodInfo GetBinOpsMethod(string name, Type[] types) + { + return ScriptCodeGen.GetStaticMethod(typeof(BinOpStr), name, types); + } + + /** + * @brief Create a dictionary for processing binary operators. + * This tells us, for a given type, an operator and another type, + * is the operation permitted, and if so, what is the type of the result? + * The key is , + * where and are strings returned by (TokenType...).ToString() + * and is string returned by (TokenKw...).ToString() + * The value is a BinOpStr struct giving the resultant type and a method to generate the code. + */ + private static Dictionary DefineBinOps() + { + Dictionary bos = new Dictionary(); + + string[] booltypes = new string[] { "bool", "char", "float", "integer", "key", "list", "string" }; + + /* + * Get the && and || all out of the way... + * Simply cast their left and right operands to boolean then process. + */ + for(int i = 0; i < booltypes.Length; i++) + { + for(int j = 0; j < booltypes.Length; j++) + { + bos.Add(booltypes[i] + "&&" + booltypes[j], + new BinOpStr(typeof(bool), BinOpStrAndAnd)); + bos.Add(booltypes[i] + "||" + booltypes[j], + new BinOpStr(typeof(bool), BinOpStrOrOr)); + } + } + + /* + * Pound through all the other combinations we support. + */ + + // boolean : somethingelse + DefineBinOpsBoolX(bos, "bool"); + DefineBinOpsBoolX(bos, "char"); + DefineBinOpsBoolX(bos, "float"); + DefineBinOpsBoolX(bos, "integer"); + DefineBinOpsBoolX(bos, "key"); + DefineBinOpsBoolX(bos, "list"); + DefineBinOpsBoolX(bos, "string"); + + // stuff with chars + DefineBinOpsChar(bos); + + // somethingelse : boolean + DefineBinOpsXBool(bos, "char"); + DefineBinOpsXBool(bos, "float"); + DefineBinOpsXBool(bos, "integer"); + DefineBinOpsXBool(bos, "key"); + DefineBinOpsXBool(bos, "list"); + DefineBinOpsXBool(bos, "string"); + + // float : somethingelse + DefineBinOpsFloatX(bos, "float"); + DefineBinOpsFloatX(bos, "integer"); + + // integer : float + DefineBinOpsXFloat(bos, "integer"); + + // anything else with integers + DefineBinOpsInteger(bos); + + // key : somethingelse + DefineBinOpsKeyX(bos, "key"); + DefineBinOpsKeyX(bos, "string"); + + // string : key + DefineBinOpsXKey(bos, "string"); + + // things with lists + DefineBinOpsList(bos); + + // things with rotations + DefineBinOpsRotation(bos); + + // things with strings + DefineBinOpsString(bos); + + // things with vectors + DefineBinOpsVector(bos); + + // Contrary to some beliefs, scripts do things like string+integer and integer+string + bos.Add("bool+string", new BinOpStr(typeof(string), BinOpStrStrAddStr)); + bos.Add("char+string", new BinOpStr(typeof(string), BinOpStrStrAddStr)); + bos.Add("float+string", new BinOpStr(typeof(string), BinOpStrStrAddStr)); + bos.Add("integer+string", new BinOpStr(typeof(string), BinOpStrStrAddStr)); + bos.Add("string+bool", new BinOpStr(typeof(string), BinOpStrStrAddStr, true)); + bos.Add("string+char", new BinOpStr(typeof(string), BinOpStrStrAddStr, true)); + bos.Add("string+float", new BinOpStr(typeof(string), BinOpStrStrAddStr, true)); + bos.Add("string+integer", new BinOpStr(typeof(string), BinOpStrStrAddStr, true)); + + // Now for our final slight-of-hand, we're going to scan through all those. + // And wherever we see an 'integer' in the key, we are going to make another + // entry with 'bool', as we want to accept a bool as having a value of 0 or 1. + // This lets us do things like 3.5 * (x > 0). + + Dictionary bos2 = new Dictionary(); + foreach(KeyValuePair kvp in bos) + { + string key = kvp.Key; + BinOpStr val = kvp.Value; + bos2.Add(key, val); + } + Regex wordReg = new Regex("\\w+"); + Regex opReg = new Regex("\\W+"); + foreach(KeyValuePair kvp in bos) + { + string key = kvp.Key; + BinOpStr val = kvp.Value; + MatchCollection matches = wordReg.Matches(key); + if(matches.Count != 2) + continue; + Match opM = opReg.Match(key); + if(!opM.Success) + continue; + string left = matches[0].Value; + string right = matches[1].Value; + string op = opM.Value; + string key2; + if(left == "integer" && right == "integer") + { + key2 = "bool" + op + "bool"; + if(!bos2.ContainsKey(key2)) + bos2.Add(key2, val); + key2 = "bool" + op + "integer"; + if(!bos2.ContainsKey(key2)) + bos2.Add(key2, val); + key2 = "integer" + op + "bool"; + if(!bos2.ContainsKey(key2)) + bos2.Add(key2, val); + } + else + { + key2 = key.Replace("integer", "bool"); + if(!bos2.ContainsKey(key2)) + bos2.Add(key2, val); + } + } + return bos2; + } + + private static void DefineBinOpsBoolX(Dictionary bos, string x) + { + bos.Add("bool|" + x, new BinOpStr(typeof(int), BinOpStrBoolOrX)); + bos.Add("bool^" + x, new BinOpStr(typeof(int), BinOpStrBoolXorX)); + bos.Add("bool&" + x, new BinOpStr(typeof(int), BinOpStrBoolAndX)); + bos.Add("bool==" + x, new BinOpStr(typeof(bool), BinOpStrBoolEqX)); + bos.Add("bool!=" + x, new BinOpStr(typeof(bool), BinOpStrBoolNeX)); + } + + private static void DefineBinOpsXBool(Dictionary bos, string x) + { + bos.Add(x + "|bool", new BinOpStr(typeof(int), BinOpStrBoolOrX)); + bos.Add(x + "^bool", new BinOpStr(typeof(int), BinOpStrBoolXorX)); + bos.Add(x + "&bool", new BinOpStr(typeof(int), BinOpStrBoolAndX)); + bos.Add(x + "==bool", new BinOpStr(typeof(bool), BinOpStrBoolEqX)); + bos.Add(x + "!=bool", new BinOpStr(typeof(bool), BinOpStrBoolNeX)); + } + + private static void DefineBinOpsFloatX(Dictionary bos, string x) + { + bos.Add("float==" + x, new BinOpStr(typeof(bool), BinOpStrFloatEqX)); + bos.Add("float!=" + x, new BinOpStr(typeof(bool), BinOpStrFloatNeX)); + bos.Add("float<" + x, new BinOpStr(typeof(bool), BinOpStrFloatLtX)); + bos.Add("float<=" + x, new BinOpStr(typeof(bool), BinOpStrFloatLeX)); + bos.Add("float>" + x, new BinOpStr(typeof(bool), BinOpStrFloatGtX)); + bos.Add("float>=" + x, new BinOpStr(typeof(bool), BinOpStrFloatGeX)); + bos.Add("float+" + x, new BinOpStr(typeof(double), BinOpStrFloatAddX, true)); + bos.Add("float-" + x, new BinOpStr(typeof(double), BinOpStrFloatSubX, true)); + bos.Add("float*" + x, new BinOpStr(typeof(double), BinOpStrFloatMulX, true)); + bos.Add("float/" + x, new BinOpStr(typeof(double), BinOpStrFloatDivX, true)); + bos.Add("float%" + x, new BinOpStr(typeof(double), BinOpStrFloatModX, true)); + } + + private static void DefineBinOpsXFloat(Dictionary bos, string x) + { + bos.Add(x + "==float", new BinOpStr(typeof(bool), BinOpStrXEqFloat)); + bos.Add(x + "!=float", new BinOpStr(typeof(bool), BinOpStrXNeFloat)); + bos.Add(x + "float", new BinOpStr(typeof(bool), BinOpStrXGtFloat)); + bos.Add(x + ">=float", new BinOpStr(typeof(bool), BinOpStrXGeFloat)); + bos.Add(x + "+float", new BinOpStr(typeof(double), BinOpStrXAddFloat, true)); + bos.Add(x + "-float", new BinOpStr(typeof(double), BinOpStrXSubFloat, true)); + bos.Add(x + "*float", new BinOpStr(typeof(double), BinOpStrXMulFloat, true)); + bos.Add(x + "/float", new BinOpStr(typeof(double), BinOpStrXDivFloat, true)); + bos.Add(x + "%float", new BinOpStr(typeof(double), BinOpStrXModFloat, true)); + } + + private static void DefineBinOpsChar(Dictionary bos) + { + bos.Add("char==char", new BinOpStr(typeof(bool), BinOpStrCharEqChar)); + bos.Add("char!=char", new BinOpStr(typeof(bool), BinOpStrCharNeChar)); + bos.Add("charchar", new BinOpStr(typeof(bool), BinOpStrCharGtChar)); + bos.Add("char>=char", new BinOpStr(typeof(bool), BinOpStrCharGeChar)); + bos.Add("char+integer", new BinOpStr(typeof(char), BinOpStrCharAddInt, true)); + bos.Add("char-integer", new BinOpStr(typeof(char), BinOpStrCharSubInt, true)); + bos.Add("char-char", new BinOpStr(typeof(int), BinOpStrCharSubChar)); + } + + private static void DefineBinOpsInteger(Dictionary bos) + { + bos.Add("integer==integer", new BinOpStr(typeof(bool), BinOpStrIntEqInt)); + bos.Add("integer!=integer", new BinOpStr(typeof(bool), BinOpStrIntNeInt)); + bos.Add("integerinteger", new BinOpStr(typeof(bool), BinOpStrIntGtInt)); + bos.Add("integer>=integer", new BinOpStr(typeof(bool), BinOpStrIntGeInt)); + bos.Add("integer|integer", new BinOpStr(typeof(int), BinOpStrIntOrInt, true)); + bos.Add("integer^integer", new BinOpStr(typeof(int), BinOpStrIntXorInt, true)); + bos.Add("integer&integer", new BinOpStr(typeof(int), BinOpStrIntAndInt, true)); + bos.Add("integer+integer", new BinOpStr(typeof(int), BinOpStrIntAddInt, true)); + bos.Add("integer-integer", new BinOpStr(typeof(int), BinOpStrIntSubInt, true)); + bos.Add("integer*integer", new BinOpStr(typeof(int), BinOpStrIntMulInt, true)); + bos.Add("integer/integer", new BinOpStr(typeof(int), BinOpStrIntDivInt, true)); + bos.Add("integer%integer", new BinOpStr(typeof(int), BinOpStrIntModInt, true)); + bos.Add("integer<>integer", new BinOpStr(typeof(int), BinOpStrIntShrInt, true)); + } + + private static void DefineBinOpsKeyX(Dictionary bos, string x) + { + bos.Add("key==" + x, new BinOpStr(typeof(bool), BinOpStrKeyEqX)); + bos.Add("key!=" + x, new BinOpStr(typeof(bool), BinOpStrKeyNeX)); + } + + private static void DefineBinOpsXKey(Dictionary bos, string x) + { + bos.Add(x + "==key", new BinOpStr(typeof(bool), BinOpStrKeyEqX)); + bos.Add(x + "!=key", new BinOpStr(typeof(bool), BinOpStrKeyNeX)); + } + + private static void DefineBinOpsList(Dictionary bos) + { + bos.Add("list+float", new BinOpStr(typeof(LSL_List), BinOpStrListAddFloat, true)); + bos.Add("list+integer", new BinOpStr(typeof(LSL_List), BinOpStrListAddInt, true)); + bos.Add("list+key", new BinOpStr(typeof(LSL_List), BinOpStrListAddKey, true)); + bos.Add("list+list", new BinOpStr(typeof(LSL_List), BinOpStrListAddList, true)); + bos.Add("list+rotation", new BinOpStr(typeof(LSL_List), BinOpStrListAddRot, true)); + bos.Add("list+string", new BinOpStr(typeof(LSL_List), BinOpStrListAddStr, true)); + bos.Add("list+vector", new BinOpStr(typeof(LSL_List), BinOpStrListAddVec, true)); + + bos.Add("float+list", new BinOpStr(typeof(LSL_List), BinOpStrFloatAddList)); + bos.Add("integer+list", new BinOpStr(typeof(LSL_List), BinOpStrIntAddList)); + bos.Add("key+list", new BinOpStr(typeof(LSL_List), BinOpStrKeyAddList)); + bos.Add("rotation+list", new BinOpStr(typeof(LSL_List), BinOpStrRotAddList)); + bos.Add("string+list", new BinOpStr(typeof(LSL_List), BinOpStrStrAddList)); + bos.Add("vector+list", new BinOpStr(typeof(LSL_List), BinOpStrVecAddList)); + + bos.Add("list==list", new BinOpStr(typeof(bool), BinOpStrListEqList)); + bos.Add("list!=list", new BinOpStr(typeof(int), BinOpStrListNeList)); + } + + // all operations allowed by LSL_Rotation definition + private static void DefineBinOpsRotation(Dictionary bos) + { + bos.Add("rotation==rotation", new BinOpStr(typeof(bool), BinOpStrRotEqRot)); + bos.Add("rotation!=rotation", new BinOpStr(typeof(bool), BinOpStrRotNeRot)); + bos.Add("rotation+rotation", new BinOpStr(typeof(LSL_Rotation), BinOpStrRotAddRot, true)); + bos.Add("rotation-rotation", new BinOpStr(typeof(LSL_Rotation), BinOpStrRotSubRot, true)); + bos.Add("rotation*rotation", new BinOpStr(typeof(LSL_Rotation), BinOpStrRotMulRot, true)); + bos.Add("rotation/rotation", new BinOpStr(typeof(LSL_Rotation), BinOpStrRotDivRot, true)); + } + + private static void DefineBinOpsString(Dictionary bos) + { + bos.Add("string==string", new BinOpStr(typeof(bool), BinOpStrStrEqStr)); + bos.Add("string!=string", new BinOpStr(typeof(bool), BinOpStrStrNeStr)); + bos.Add("stringstring", new BinOpStr(typeof(bool), BinOpStrStrGtStr)); + bos.Add("string>=string", new BinOpStr(typeof(bool), BinOpStrStrGeStr)); + bos.Add("string+string", new BinOpStr(typeof(string), BinOpStrStrAddStr, true)); + } + + // all operations allowed by LSL_Vector definition + private static void DefineBinOpsVector(Dictionary bos) + { + bos.Add("vector==vector", new BinOpStr(typeof(bool), BinOpStrVecEqVec)); + bos.Add("vector!=vector", new BinOpStr(typeof(bool), BinOpStrVecNeVec)); + bos.Add("vector+vector", new BinOpStr(typeof(LSL_Vector), BinOpStrVecAddVec, true)); + bos.Add("vector-vector", new BinOpStr(typeof(LSL_Vector), BinOpStrVecSubVec, true)); + bos.Add("vector*vector", new BinOpStr(typeof(double), BinOpStrVecMulVec)); + bos.Add("vector%vector", new BinOpStr(typeof(LSL_Vector), BinOpStrVecModVec, true)); + + bos.Add("vector*float", new BinOpStr(typeof(LSL_Vector), BinOpStrVecMulFloat, true)); + bos.Add("float*vector", new BinOpStr(typeof(LSL_Vector), BinOpStrFloatMulVec)); + bos.Add("vector/float", new BinOpStr(typeof(LSL_Vector), BinOpStrVecDivFloat, true)); + + bos.Add("vector*integer", new BinOpStr(typeof(LSL_Vector), BinOpStrVecMulInt, true)); + bos.Add("integer*vector", new BinOpStr(typeof(LSL_Vector), BinOpStrIntMulVec)); + bos.Add("vector/integer", new BinOpStr(typeof(LSL_Vector), BinOpStrVecDivInt, true)); + + bos.Add("vector*rotation", new BinOpStr(typeof(LSL_Vector), BinOpStrVecMulRot, true)); + bos.Add("vector/rotation", new BinOpStr(typeof(LSL_Vector), BinOpStrVecDivRot, true)); + } + + /** + * @brief These methods actually emit the code to perform the arithmetic. + * @param scg = what script we are compiling + * @param left = left-hand operand location in memory (type as given by BinOpStr entry) + * @param right = right-hand operand location in memory (type as given by BinOpStr entry) + * @param result = result location in memory (type as given by BinOpStr entry) + */ + private static void BinOpStrAndAnd(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeBool); + right.PushVal(scg, errorAt, tokenTypeBool); + scg.ilGen.Emit(errorAt, OpCodes.And); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrOrOr(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeBool); + right.PushVal(scg, errorAt, tokenTypeBool); + scg.ilGen.Emit(errorAt, OpCodes.Or); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrBoolOrX(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeInt); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Or); + result.PopPost(scg, errorAt, tokenTypeInt); + } + + private static void BinOpStrBoolXorX(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeInt); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Xor); + result.PopPost(scg, errorAt, tokenTypeInt); + } + + private static void BinOpStrBoolAndX(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeInt); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.And); + result.PopPost(scg, errorAt, tokenTypeInt); + } + + private static void BinOpStrBoolEqX(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeBool); + right.PushVal(scg, errorAt, tokenTypeBool); + scg.ilGen.Emit(errorAt, OpCodes.Ceq); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrBoolNeX(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeBool); + right.PushVal(scg, errorAt, tokenTypeBool); + scg.ilGen.Emit(errorAt, OpCodes.Xor); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrFloatEqX(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Ceq); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrFloatNeX(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Ceq); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_1); + scg.ilGen.Emit(errorAt, OpCodes.Xor); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrFloatLtX(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Clt); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrFloatLeX(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Cgt); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_1); + scg.ilGen.Emit(errorAt, OpCodes.Xor); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrFloatGtX(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Cgt); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrFloatGeX(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Clt); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_1); + scg.ilGen.Emit(errorAt, OpCodes.Xor); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrFloatAddX(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Add); + result.PopPost(scg, errorAt, tokenTypeFloat); + } + + private static void BinOpStrFloatSubX(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Sub); + result.PopPost(scg, errorAt, tokenTypeFloat); + } + + private static void BinOpStrFloatMulX(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Mul); + result.PopPost(scg, errorAt, tokenTypeFloat); + } + + private static void BinOpStrFloatDivX(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Div); + result.PopPost(scg, errorAt, tokenTypeFloat); + } + + private static void BinOpStrFloatModX(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Rem); + result.PopPost(scg, errorAt, tokenTypeFloat); + } + + private static void BinOpStrXEqFloat(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Ceq); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrXNeFloat(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Ceq); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_1); + scg.ilGen.Emit(errorAt, OpCodes.Xor); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrXLtFloat(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Clt); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrXLeFloat(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Cgt); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_1); + scg.ilGen.Emit(errorAt, OpCodes.Xor); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrXGtFloat(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Cgt); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrXGeFloat(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Clt); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_1); + scg.ilGen.Emit(errorAt, OpCodes.Xor); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrXAddFloat(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Add); + result.PopPost(scg, errorAt, tokenTypeFloat); + } + + private static void BinOpStrXSubFloat(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Sub); + result.PopPost(scg, errorAt, tokenTypeFloat); + } + + private static void BinOpStrXMulFloat(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Mul); + result.PopPost(scg, errorAt, tokenTypeFloat); + } + + private static void BinOpStrXDivFloat(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Div); + result.PopPost(scg, errorAt, tokenTypeFloat); + } + + private static void BinOpStrXModFloat(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Rem); + result.PopPost(scg, errorAt, tokenTypeFloat); + } + + private static void BinOpStrCharEqChar(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeChar); + right.PushVal(scg, errorAt, tokenTypeChar); + scg.ilGen.Emit(errorAt, OpCodes.Ceq); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrCharNeChar(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeChar); + right.PushVal(scg, errorAt, tokenTypeChar); + scg.ilGen.Emit(errorAt, OpCodes.Ceq); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_1); + scg.ilGen.Emit(errorAt, OpCodes.Xor); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrCharLtChar(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeChar); + right.PushVal(scg, errorAt, tokenTypeChar); + scg.ilGen.Emit(errorAt, OpCodes.Clt); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrCharLeChar(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeChar); + right.PushVal(scg, errorAt, tokenTypeChar); + scg.ilGen.Emit(errorAt, OpCodes.Cgt); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_1); + scg.ilGen.Emit(errorAt, OpCodes.Xor); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrCharGtChar(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeChar); + right.PushVal(scg, errorAt, tokenTypeChar); + scg.ilGen.Emit(errorAt, OpCodes.Cgt); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrCharGeChar(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeChar); + right.PushVal(scg, errorAt, tokenTypeChar); + scg.ilGen.Emit(errorAt, OpCodes.Clt); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_1); + scg.ilGen.Emit(errorAt, OpCodes.Xor); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrCharAddInt(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeChar); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Add); + result.PopPost(scg, errorAt, tokenTypeChar); + } + + private static void BinOpStrCharSubInt(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeChar); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Sub); + result.PopPost(scg, errorAt, tokenTypeChar); + } + + private static void BinOpStrCharSubChar(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeChar); + right.PushVal(scg, errorAt, tokenTypeChar); + scg.ilGen.Emit(errorAt, OpCodes.Sub); + result.PopPost(scg, errorAt, tokenTypeInt); + } + + private static void BinOpStrIntEqInt(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeInt); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Ceq); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrIntNeInt(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeInt); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Ceq); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_1); + scg.ilGen.Emit(errorAt, OpCodes.Xor); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrIntLtInt(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeInt); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Clt); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrIntLeInt(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeInt); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Cgt); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_1); + scg.ilGen.Emit(errorAt, OpCodes.Xor); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrIntGtInt(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeInt); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Cgt); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrIntGeInt(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeInt); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Clt); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_1); + scg.ilGen.Emit(errorAt, OpCodes.Xor); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrIntOrInt(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeInt); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Or); + result.PopPost(scg, errorAt, tokenTypeInt); + } + + private static void BinOpStrIntXorInt(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeInt); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Xor); + result.PopPost(scg, errorAt, tokenTypeInt); + } + + private static void BinOpStrIntAndInt(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeInt); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.And); + result.PopPost(scg, errorAt, tokenTypeInt); + } + + private static void BinOpStrIntAddInt(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeInt); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Add); + result.PopPost(scg, errorAt, tokenTypeInt); + } + + private static void BinOpStrIntSubInt(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeInt); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Sub); + result.PopPost(scg, errorAt, tokenTypeInt); + } + + private static void BinOpStrIntMulInt(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeInt); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Mul); + result.PopPost(scg, errorAt, tokenTypeInt); + } + + private static void BinOpStrIntDivInt(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + // note that we must allow 0x800000/-1 -> 0x80000000 for lslangtest1.lsl + // so sign-extend the operands to 64-bit then divide and truncate result + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Conv_I8); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Conv_I8); + scg.ilGen.Emit(errorAt, OpCodes.Div); + scg.ilGen.Emit(errorAt, OpCodes.Conv_I4); + result.PopPost(scg, errorAt, tokenTypeInt); + } + + private static void BinOpStrIntModInt(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + // note that we must allow 0x800000%-1 -> 0 for lslangtest1.lsl + // so sign-extend the operands to 64-bit then mod and truncate result + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Conv_I8); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Conv_I8); + scg.ilGen.Emit(errorAt, OpCodes.Rem); + scg.ilGen.Emit(errorAt, OpCodes.Conv_I4); + result.PopPost(scg, errorAt, tokenTypeInt); + } + + private static void BinOpStrIntShlInt(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeInt); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Shl); + result.PopPost(scg, errorAt, tokenTypeInt); + } + + private static void BinOpStrIntShrInt(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeInt); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Shr); + result.PopPost(scg, errorAt, tokenTypeInt); + } + + private static void BinOpStrKeyEqX(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeStr); + right.PushVal(scg, errorAt, tokenTypeStr); + scg.ilGen.Emit(errorAt, OpCodes.Call, stringCmpStringMethInfo); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_0); + scg.ilGen.Emit(errorAt, OpCodes.Ceq); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrKeyNeX(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeStr); + right.PushVal(scg, errorAt, tokenTypeStr); + scg.ilGen.Emit(errorAt, OpCodes.Call, stringCmpStringMethInfo); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_0); + scg.ilGen.Emit(errorAt, OpCodes.Ceq); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_1); + scg.ilGen.Emit(errorAt, OpCodes.Xor); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrListAddFloat(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeList); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethListAddFloat); + result.PopPost(scg, errorAt, tokenTypeList); + } + + private static void BinOpStrListAddInt(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeList); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethListAddInt); + result.PopPost(scg, errorAt, tokenTypeList); + } + + private static void BinOpStrListAddKey(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeList); + right.PushVal(scg, errorAt, tokenTypeStr); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethListAddKey); + result.PopPost(scg, errorAt, tokenTypeList); + } + + private static void BinOpStrListAddList(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeList); + right.PushVal(scg, errorAt, tokenTypeList); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethListAddList); + result.PopPost(scg, errorAt, tokenTypeList); + } + + private static void BinOpStrListAddRot(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeList); + right.PushVal(scg, errorAt, tokenTypeRot); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethListAddRot); + result.PopPost(scg, errorAt, tokenTypeList); + } + + private static void BinOpStrListAddStr(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeList); + right.PushVal(scg, errorAt, tokenTypeStr); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethListAddStr); + result.PopPost(scg, errorAt, tokenTypeList); + } + + private static void BinOpStrListAddVec(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeList); + right.PushVal(scg, errorAt, tokenTypeVec); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethListAddVec); + result.PopPost(scg, errorAt, tokenTypeList); + } + + private static void BinOpStrFloatAddList(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeList); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethFloatAddList); + result.PopPost(scg, errorAt, tokenTypeList); + } + + private static void BinOpStrIntAddList(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeInt); + right.PushVal(scg, errorAt, tokenTypeList); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethIntAddList); + result.PopPost(scg, errorAt, tokenTypeList); + } + + private static void BinOpStrKeyAddList(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeStr); + right.PushVal(scg, errorAt, tokenTypeList); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethKeyAddList); + result.PopPost(scg, errorAt, tokenTypeList); + } + + private static void BinOpStrRotAddList(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeRot); + right.PushVal(scg, errorAt, tokenTypeList); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethRotAddList); + result.PopPost(scg, errorAt, tokenTypeList); + } + + private static void BinOpStrStrAddList(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeStr); + right.PushVal(scg, errorAt, tokenTypeList); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethStrAddList); + result.PopPost(scg, errorAt, tokenTypeList); + } + + private static void BinOpStrVecAddList(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeVec); + right.PushVal(scg, errorAt, tokenTypeList); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethVecAddList); + result.PopPost(scg, errorAt, tokenTypeList); + } + + private static void BinOpStrListEqList(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeList); + right.PushVal(scg, errorAt, tokenTypeList); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethListEqList); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrListNeList(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeList); + right.PushVal(scg, errorAt, tokenTypeList); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethListNeList); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrRotEqRot(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeRot); + right.PushVal(scg, errorAt, tokenTypeRot); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethRotEqRot); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrRotNeRot(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeRot); + right.PushVal(scg, errorAt, tokenTypeRot); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethRotNeRot); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrRotAddRot(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeRot); + right.PushVal(scg, errorAt, tokenTypeRot); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethRotAddRot); + result.PopPost(scg, errorAt, tokenTypeRot); + } + + private static void BinOpStrRotSubRot(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeRot); + right.PushVal(scg, errorAt, tokenTypeRot); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethRotSubRot); + result.PopPost(scg, errorAt, tokenTypeRot); + } + + private static void BinOpStrRotMulRot(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeRot); + right.PushVal(scg, errorAt, tokenTypeRot); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethRotMulRot); + result.PopPost(scg, errorAt, tokenTypeRot); + } + + private static void BinOpStrRotDivRot(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeRot); + right.PushVal(scg, errorAt, tokenTypeRot); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethRotDivRot); + result.PopPost(scg, errorAt, tokenTypeRot); + } + + private static void BinOpStrStrEqStr(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeStr); + right.PushVal(scg, errorAt, tokenTypeStr); + scg.ilGen.Emit(errorAt, OpCodes.Call, stringCmpStringMethInfo); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_0); + scg.ilGen.Emit(errorAt, OpCodes.Ceq); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrStrNeStr(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeStr); + right.PushVal(scg, errorAt, tokenTypeStr); + scg.ilGen.Emit(errorAt, OpCodes.Call, stringCmpStringMethInfo); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_0); + scg.ilGen.Emit(errorAt, OpCodes.Ceq); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_1); + scg.ilGen.Emit(errorAt, OpCodes.Xor); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrStrLtStr(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeStr); + right.PushVal(scg, errorAt, tokenTypeStr); + scg.ilGen.Emit(errorAt, OpCodes.Call, stringCmpStringMethInfo); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_0); + scg.ilGen.Emit(errorAt, OpCodes.Clt); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrStrLeStr(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeStr); + right.PushVal(scg, errorAt, tokenTypeStr); + scg.ilGen.Emit(errorAt, OpCodes.Call, stringCmpStringMethInfo); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_1); + scg.ilGen.Emit(errorAt, OpCodes.Clt); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrStrGtStr(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeStr); + right.PushVal(scg, errorAt, tokenTypeStr); + scg.ilGen.Emit(errorAt, OpCodes.Call, stringCmpStringMethInfo); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_0); + scg.ilGen.Emit(errorAt, OpCodes.Cgt); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrStrGeStr(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeStr); + right.PushVal(scg, errorAt, tokenTypeStr); + scg.ilGen.Emit(errorAt, OpCodes.Call, stringCmpStringMethInfo); + scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_M1); + scg.ilGen.Emit(errorAt, OpCodes.Cgt); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + // Called by many type combinations so both operands need to be cast to strings + private static void BinOpStrStrAddStr(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeStr); + right.PushVal(scg, errorAt, tokenTypeStr); + scg.ilGen.Emit(errorAt, OpCodes.Call, stringAddStringMethInfo); + result.PopPost(scg, errorAt, tokenTypeStr); + } + + private static void BinOpStrVecEqVec(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeVec); + right.PushVal(scg, errorAt, tokenTypeVec); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethVecEqVec); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrVecNeVec(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeVec); + right.PushVal(scg, errorAt, tokenTypeVec); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethVecNeVec); + result.PopPost(scg, errorAt, tokenTypeBool); + } + + private static void BinOpStrVecAddVec(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeVec); + right.PushVal(scg, errorAt, tokenTypeVec); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethVecAddVec); + result.PopPost(scg, errorAt, tokenTypeVec); + } + + private static void BinOpStrVecSubVec(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeVec); + right.PushVal(scg, errorAt, tokenTypeVec); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethVecSubVec); + result.PopPost(scg, errorAt, tokenTypeVec); + } + + private static void BinOpStrVecMulVec(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeVec); + right.PushVal(scg, errorAt, tokenTypeVec); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethVecMulVec); + result.PopPost(scg, errorAt, tokenTypeFloat); + } + + private static void BinOpStrVecModVec(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeVec); + right.PushVal(scg, errorAt, tokenTypeVec); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethVecModVec); + result.PopPost(scg, errorAt, tokenTypeVec); + } + + private static void BinOpStrVecMulFloat(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeVec); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethVecMulFloat); + result.PopPost(scg, errorAt, tokenTypeVec); + } + + private static void BinOpStrFloatMulVec(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeFloat); + right.PushVal(scg, errorAt, tokenTypeVec); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethFloatMulVec); + result.PopPost(scg, errorAt, tokenTypeVec); + } + + private static void BinOpStrVecDivFloat(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeVec); + right.PushVal(scg, errorAt, tokenTypeFloat); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethVecDivFloat); + result.PopPost(scg, errorAt, tokenTypeVec); + } + + private static void BinOpStrVecMulInt(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeVec); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethVecMulInt); + result.PopPost(scg, errorAt, tokenTypeVec); + } + + private static void BinOpStrIntMulVec(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeInt); + right.PushVal(scg, errorAt, tokenTypeVec); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethIntMulVec); + result.PopPost(scg, errorAt, tokenTypeVec); + } + + private static void BinOpStrVecDivInt(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeVec); + right.PushVal(scg, errorAt, tokenTypeInt); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethVecDivInt); + result.PopPost(scg, errorAt, tokenTypeVec); + } + + private static void BinOpStrVecMulRot(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeVec); + right.PushVal(scg, errorAt, tokenTypeRot); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethVecMulRot); + result.PopPost(scg, errorAt, tokenTypeVec); + } + + private static void BinOpStrVecDivRot(ScriptCodeGen scg, Token errorAt, CompValu left, CompValu right, CompValu result) + { + result.PopPre(scg, errorAt); + left.PushVal(scg, errorAt, tokenTypeVec); + right.PushVal(scg, errorAt, tokenTypeRot); + scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethVecDivRot); + result.PopPost(scg, errorAt, tokenTypeVec); + } + + /** + * @brief These methods are called at runtime as helpers. + * Needed to pick up functionality defined by overloaded operators of LSL_ types. + * They need to be marked public or runtime says they are inaccessible. + */ + public static LSL_List MethListAddFloat(LSL_List left, double right) + { + return MethListAddObj(left, new LSL_Float(right)); + } + public static LSL_List MethListAddInt(LSL_List left, int right) + { + return MethListAddObj(left, new LSL_Integer(right)); + } + public static LSL_List MethListAddKey(LSL_List left, string right) + { + return MethListAddObj(left, new LSL_Key(right)); + } + public static LSL_List MethListAddRot(LSL_List left, LSL_Rotation right) + { + return MethListAddObj(left, right); + } + public static LSL_List MethListAddStr(LSL_List left, string right) + { + return MethListAddObj(left, new LSL_String(right)); + } + public static LSL_List MethListAddVec(LSL_List left, LSL_Vector right) + { + return MethListAddObj(left, right); + } + public static LSL_List MethListAddObj(LSL_List left, object right) + { + int oldlen = left.Length; + object[] newarr = new object[oldlen + 1]; + Array.Copy(left.Data, newarr, oldlen); + newarr[oldlen] = right; + return new LSL_List(newarr); + } + + public static LSL_List MethListAddList(LSL_List left, LSL_List right) + { + int leftlen = left.Length; + int ritelen = right.Length; + object[] newarr = new object[leftlen + ritelen]; + Array.Copy(left.Data, newarr, leftlen); + Array.Copy(right.Data, 0, newarr, leftlen, ritelen); + return new LSL_List(newarr); + } + + public static LSL_List MethFloatAddList(double left, LSL_List right) + { + return MethObjAddList(new LSL_Float(left), right); + } + public static LSL_List MethIntAddList(int left, LSL_List right) + { + return MethObjAddList(new LSL_Integer(left), right); + } + public static LSL_List MethKeyAddList(string left, LSL_List right) + { + return MethObjAddList(new LSL_Key(left), right); + } + public static LSL_List MethRotAddList(LSL_Rotation left, LSL_List right) + { + return MethObjAddList(left, right); + } + public static LSL_List MethStrAddList(string left, LSL_List right) + { + return MethObjAddList(new LSL_String(left), right); + } + public static LSL_List MethVecAddList(LSL_Vector left, LSL_List right) + { + return MethObjAddList(left, right); + } + public static LSL_List MethObjAddList(object left, LSL_List right) + { + int oldlen = right.Length; + object[] newarr = new object[oldlen + 1]; + newarr[0] = left; + Array.Copy(right.Data, 0, newarr, 1, oldlen); + return new LSL_List(newarr); + } + + public static bool MethListEqList(LSL_List left, LSL_List right) + { + return left == right; + } + + // According to http://wiki.secondlife.com/wiki/LlGetListLength + // jackassed LSL allows 'somelist != []' to get the length of a list + public static int MethListNeList(LSL_List left, LSL_List right) + { + int leftlen = left.Length; + int ritelen = right.Length; + return leftlen - ritelen; + } + + public static bool MethRotEqRot(LSL_Rotation left, LSL_Rotation right) + { + return left == right; + } + + public static bool MethRotNeRot(LSL_Rotation left, LSL_Rotation right) + { + return left != right; + } + + public static LSL_Rotation MethRotAddRot(LSL_Rotation left, LSL_Rotation right) + { + return left + right; + } + + public static LSL_Rotation MethRotSubRot(LSL_Rotation left, LSL_Rotation right) + { + return left - right; + } + + public static LSL_Rotation MethRotMulRot(LSL_Rotation left, LSL_Rotation right) + { + return left * right; + } + + public static LSL_Rotation MethRotDivRot(LSL_Rotation left, LSL_Rotation right) + { + return left / right; + } + + public static bool MethVecEqVec(LSL_Vector left, LSL_Vector right) + { + return left == right; + } + + public static bool MethVecNeVec(LSL_Vector left, LSL_Vector right) + { + return left != right; + } + + public static LSL_Vector MethVecAddVec(LSL_Vector left, LSL_Vector right) + { + return left + right; + } + + public static LSL_Vector MethVecSubVec(LSL_Vector left, LSL_Vector right) + { + return left - right; + } + + public static double MethVecMulVec(LSL_Vector left, LSL_Vector right) + { + return (double)(left * right).value; + } + + public static LSL_Vector MethVecModVec(LSL_Vector left, LSL_Vector right) + { + return left % right; + } + + public static LSL_Vector MethVecMulFloat(LSL_Vector left, double right) + { + return left * right; + } + + public static LSL_Vector MethFloatMulVec(double left, LSL_Vector right) + { + return left * right; + } + + public static LSL_Vector MethVecDivFloat(LSL_Vector left, double right) + { + return left / right; + } + + public static LSL_Vector MethVecMulInt(LSL_Vector left, int right) + { + return left * right; + } + + public static LSL_Vector MethIntMulVec(int left, LSL_Vector right) + { + return left * right; + } + + public static LSL_Vector MethVecDivInt(LSL_Vector left, int right) + { + return left / right; + } + + public static LSL_Vector MethVecMulRot(LSL_Vector left, LSL_Rotation right) + { + return left * right; + } + + public static LSL_Vector MethVecDivRot(LSL_Vector left, LSL_Rotation right) + { + return left / right; + } + } +} -- cgit v1.1