text:
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<string, BinOpStr> defined = DefineBinOps();

        public Type outtype;           // type of result of computation
        public BinOpStrEmitBO emitBO;  // how to compute result
        public bool rmwOK;             // is the <operator>= 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 <lefttype><opcode><righttype>,
         *   where <lefttype> and <righttype> are strings returned by (TokenType...).ToString()
         *   and <opcode> 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<string, BinOpStr> DefineBinOps()
        {
            Dictionary<string, BinOpStr> bos = new Dictionary<string, BinOpStr>();

            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<string, BinOpStr> bos2 = new Dictionary<string, BinOpStr>();
            foreach(KeyValuePair<string, BinOpStr> 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<string, BinOpStr> 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<string, BinOpStr> 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<string, BinOpStr> 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<string, BinOpStr> 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<string, BinOpStr> 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), BinOpStrXLtFloat));
            bos.Add(x + "<=float", new BinOpStr(typeof(bool), BinOpStrXLeFloat));
            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<string, BinOpStr> bos)
        {
            bos.Add("char==char", new BinOpStr(typeof(bool), BinOpStrCharEqChar));
            bos.Add("char!=char", new BinOpStr(typeof(bool), BinOpStrCharNeChar));
            bos.Add("char<char", new BinOpStr(typeof(bool), BinOpStrCharLtChar));
            bos.Add("char<=char", new BinOpStr(typeof(bool), BinOpStrCharLeChar));
            bos.Add("char>char", 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<string, BinOpStr> bos)
        {
            bos.Add("integer==integer", new BinOpStr(typeof(bool), BinOpStrIntEqInt));
            bos.Add("integer!=integer", new BinOpStr(typeof(bool), BinOpStrIntNeInt));
            bos.Add("integer<integer", new BinOpStr(typeof(bool), BinOpStrIntLtInt));
            bos.Add("integer<=integer", new BinOpStr(typeof(bool), BinOpStrIntLeInt));
            bos.Add("integer>integer", 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), BinOpStrIntShlInt, true));
            bos.Add("integer>>integer", new BinOpStr(typeof(int), BinOpStrIntShrInt, true));
        }

        private static void DefineBinOpsKeyX(Dictionary<string, BinOpStr> 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<string, BinOpStr> 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<string, BinOpStr> 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<string, BinOpStr> 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<string, BinOpStr> bos)
        {
            bos.Add("string==string", new BinOpStr(typeof(bool), BinOpStrStrEqStr));
            bos.Add("string!=string", new BinOpStr(typeof(bool), BinOpStrStrNeStr));
            bos.Add("string<string", new BinOpStr(typeof(bool), BinOpStrStrLtStr));
            bos.Add("string<=string", new BinOpStr(typeof(bool), BinOpStrStrLeStr));
            bos.Add("string>string", 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<string, BinOpStr> 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;
        }
    }
}


text:
title: Failure.filterNot - Kotlin utilities
---

[Kotlin utilities](../../index.html) / [it.czerwinski.kotlin.util](../index.html) / [Failure](index.html) / [filterNot](./filter-not.html)

# filterNot

`fun filterNot(predicate: (`[`Nothing`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-nothing/index.html)`) -> `[`Boolean`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html)`): `[`Try`](../-try/index.html)`<`[`Nothing`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-nothing/index.html)`>`

Overrides [Try.filterNot](../-try/filter-not.html)

Returns the same [Success](../-success/index.html) if the [predicate](../-try/filter-not.html#it.czerwinski.kotlin.util.Try$filterNot(kotlin.Function1((it.czerwinski.kotlin.util.Try.T, kotlin.Boolean)))/predicate) is not satisfied for the value. Otherwise returns a [Failure](index.html).

### Parameters

`predicate` - Predicate function.

**Return**
The same [Success](../-success/index.html) if the [predicate](../-try/filter-not.html#it.czerwinski.kotlin.util.Try$filterNot(kotlin.Function1((it.czerwinski.kotlin.util.Try.T, kotlin.Boolean)))/predicate) is not satisfied for the value. Otherwise returns a [Failure](index.html).

redpajama_set_name: RedPajamaGithub


text:
Edit {{centre.name}} details

Contact details

Phone

{{centre.phone}}

Email

{{centre.email}}

Address

{{ centre.fullAddress | safe }}

Opening Times

            {% for day in centre.openingTimes %}

{{ day.day }}

{{ day.open }}

            {% endfor %}

Facilities

            {% for text in centre.details %}

{{text}}

            {% endfor %}


text:
Integration of runtime-health with netflix eureka. This package provides bridging of health state and eureka status as a registered HealthCheckHandler for EurekaClient.
The HealthCheckHandler registration with EurekaClient will not occur until after the Injector is created.

To use:
```java
InjectorBuilder
    .fromModules(
        // ... other modules ...
        new HealthModule(),
        new EurekaHealthStatusBridgeModule(),
        // ... other modules ...
    )
    .createInjector();
```

### Archaius2-backed IndicatorMatcher
Filtering of which HealthIndicators will be used in communicating the health status of the application is provided via an [Archaius2](https://github.com/Netflix/archaius/tree/2.x) implementation of [IndicatorMatcher](https://github.com/Netflix/runtime-health/tree/health-api/src/main/java/com/netflix/runtime/health/api/IndicatorMatcher.java).

```
InjectorBuilder
    .fromModules(
        // ... other modules ...
        new HealthModule(),
        new EurekaHealthStatusBridgeModule(),
        new ArchaiusHealthStatusFilterModule(),
        // ... other modules ...
    )
    .createInjector();
```

Indicators can now be included/excluded by setting the following properties in Archaius2. Excluded indicators will take priority over included ones.
```
health.status.indicators.include=com.myproject.MyIndicator
health.status.indicators.exclude=com.myproject.DontIncludeThisIndicator
```


text:
import { GitgraphCore } from "../gitgraph";

describe("Gitgraph.commit", () => {
  describe("initial commit", () => {
    it("should add the initial commit", () => {
      const core = new GitgraphCore();
      const gitgraph = core.getUserApi();

      gitgraph.commit({ subject: "Initial commit" });

      const { commits } = core.getRenderedData();
      const [commit] = commits;

      expect(commits.length).toBe(1);
      expect(commit).toMatchObject({
        subject: "Initial commit",
        author: {
          name: "Sergio Flores",
          email: "saxo-guy@epic.com",
        },
        committer: {
          name: "Sergio Flores",
          email: "saxo-guy@epic.com",
        },
        refs: ["master", "HEAD"],
      });
    });

    it("should add the initial commit with another author", () => {
      const core = new GitgraphCore();
      const gitgraph = core.getUserApi();

      gitgraph.commit({
        subject: "Initial commit",
        author: "Fabien BERNARD <fabien0102@gmail.com>",
      });

      const { commits } = core.getRenderedData();
      const [commit] = commits;

      expect(commits.length).toBe(1);
      expect(commit).toMatchObject({
        subject: "Initial commit",
        refs: ["master", "HEAD"],
        author: {
          name: "Fabien BERNARD",
          email: "fabien0102@gmail.com",
        },
        committer: {
          name: "Fabien BERNARD",
          email: "fabien0102@gmail.com",
        },
      });
    });

    it("should works with the shorter commit message syntax", () => {
      const core = new GitgraphCore();
      const gitgraph = core.getUserApi();

      gitgraph.commit("Initial commit");

      const { commits } = core.getRenderedData();
      const [commit] = commits;

      expect(commits.length).toBe(1);
      expect(commit.subject).toBe("Initial commit");
    });

    it("should works without argument (default message)", () => {
      const core = new GitgraphCore();
      const gitgraph = core.getUserApi();

      gitgraph.commit();

      const { commits } = core.getRenderedData();
      const [commit] = commits;

      expect(commits.length).toBe(1);
      expect(commit.subject).toBe("He doesn't like George Michael! Boooo!");
    });
  });

  describe("two commits", () => {
    let one, two;

    beforeEach(() => {
      const core = new GitgraphCore();
      const gitgraph = core.getUserApi();

      gitgraph.commit("Initial commit").commit("Second commit");

      const { commits } = core.getRenderedData();
      [one, two] = commits;
    });

    it("should set the HEAD/master refs to the last commit", () => {
      expect(one.subject).toBe("Initial commit");
      expect(one.refs).toEqual([]);

      expect(two.subject).toBe("Second commit");
      expect(two.refs).toEqual(["master", "HEAD"]);
    });

    it("should have the first commit as parent refs", () => {
      expect(two.parents).toEqual([one.hash]);
      expect(two.parentsAbbrev).toEqual([one.hashAbbrev]);
    });
  });

  it("should use given algorithm to generate commit hash", () => {
    let index = 0;
    const core = new GitgraphCore({
      generateCommitHash: () => {
        index += 1;
        return `commit${index}`;
      },
    });
    const gitgraph = core.getUserApi();

    gitgraph.commit().commit();

    const { commits } = core.getRenderedData();
    const [commit1, commit2] = commits;

    expect(commit1.hash).toBe("commit1");
    expect(commit2.hash).toBe("commit2");
  });
});


text:
package com.github.booknara.blockphonecall.telephony;

import android.content.Context;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;

import com.github.booknara.blockphonecall.R;
import com.github.booknara.blockphonecall.util.PrefsUtil;

public final class BlockCallsTelephoneStateListener extends PhoneStateListener {
    private static final String TAG = BlockCallsTelephoneStateListener.class.getName();

    private final Context context;

    public BlockCallsTelephoneStateListener(Context context) {
        super();
        this.context = context;
    }

    @Override
    public void onCallStateChanged(int state, String number) {
        super.onCallStateChanged(state, number);

        boolean blockCall = PrefsUtil.getBoolean(context, R.string.pref_block_call);
        switch (state) {
            case TelephonyManager.CALL_STATE_IDLE:
                Log.i(TAG, "CALL_STATE_IDLE");
                break;
            case TelephonyManager.CALL_STATE_RINGING:
                Log.i(TAG, "CALL_STATE_RINGING");
                if(!blockCall)
                    return;

                TelephonyHelper.tryEndCall(context);
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                Log.i(TAG, "CALL_STATE_OFFHOOK");
                break;
            default:
                break;
        }
    }
}


text:
layout: sidebar-right
title: "Recommended new eBooks for July 2019"
date: 2019-06-27
author: lisa-brennan
category: elibrary-picks
tag: elibrary
excerpt: "We've listed some of our favourite new eBooks on OverDrive for July to help you choose your next digital read."
featured-image: /images/featured/featured-elibrary-july-2019.jpg
featured-alt: "The Never Game, All That's Dead, The Huntress"
breadcrumb: elibrary-picks
---

![The Never Game, All That's Dead, The Huntress](/images/featured/featured-elibrary-july-2019.jpg)

We're always adding great titles to our [eLibrary](/elibrary/). We've listed some of our favourite new eBooks on [OverDrive](/elibrary/overdrive/) for July to help you choose your next digital read.

See also:

* [Recommended new eAudiobooks #7](/new-suggestions/elibrary-picks/new-eaudiobooks-7/)
* [Freegal music](/elibrary/freegal/)
* [PressReader newspapers and magazines](/elibrary/press-reader/)

## [All That's Dead, by Stuart MacBride](https://suffolklibraries.overdrive.com/media/4471001)

> "Inspector Logan McRae is looking forward to a nice simple case – something to ease him back into work after a year off on the sick. But the powers-that-be have other ideas...

> "The high-profile anti-independence campaigner, Professor Wilson, has gone missing, leaving nothing but bloodstains behind. There's a war brewing between the factions for and against Scottish Nationalism. Infighting in the police ranks. And it's all playing out in the merciless glare of the media. Logan's superiors want results, and they want them now. Someone out there is trying to make a point, and they're making it in blood. If Logan can't stop them, it won't just be his career that dies."

## [Malamander, by Thomas Taylor](https://suffolklibraries.overdrive.com/media/4566992)

> "Nobody visits Eerie-on-Sea in the winter. Especially not when darkness falls and the wind howls around Maw Rocks and the wreck of the battleship Leviathan, where even now some swear they have seen the unctuous Malamander creep...

> "Herbert Lemon, Lost-and-Founder at the Grand Nautilus Hotel, knows that returning lost things to their rightful owners is not easy – especially when the lost thing is not a thing at all, but a girl. No one knows what happened to Violet Parma's parents twelve years ago, and when she engages Herbie to help her find them, the pair discover that their disappearance might have something to do with the legendary sea-monster, the Malamander.

> "Eerie-on-Sea has always been a mysteriously chilling place, where strange stories seem to wash up. And it just got stranger..."

## [The Never Game, by Jeffrey Deaver](https://suffolklibraries.overdrive.com/media/4373222)

> "Nineteen-year-old Sophie disappears one summer afternoon. She wakes up to find herself locked inside a derelict warehouse, surrounded by five objects. If she uses them wisely, she will escape her prison. Otherwise she will die.

> "Sophie's distraught father calls in the one man who can help find his daughter: unique investigator Colter Shaw. Raised in the wilderness by survivalist parents, he is an expert tracker with a forensic mind trained to solve the most challenging cases. But this will be a test even for him.

> "Soon a blogger called Henry is abducted – left to die in the dark heart of a remote forest – and the whole case gets turned on its head. Because this killer isn't following the rules; he's changing them. One murder at a time..."

## [I Heart Hawaii, by Lindsay Kelk](https://suffolklibraries.overdrive.com/media/4513829)

> "When you're running away from real life, there's only one place to go...

> "When Angela Clark's best friend Jenny invites her to join a press trip to Hawaii, three days of sun, sea and sleep sounds like the perfect antidote to her crazed life. At work in New York, she's supposed to be the face of Having It All. But the only thing Angela feels she excels at is hiding in the printer cupboard, eating Mini Cheddars and watching Netflix on her phone and if this is living the dream, she's more than ready to wake up.

> "A few days away with Jenny sounds like exactly what she needs but Angela's talent for getting into a scrape guarantees nothing goes to plan – and not even the most beautiful beaches, blue skies and daiquiris will get her off the hook..."

## [I Know Who You Are, by Alice Feeney](https://suffolklibraries.overdrive.com/media/3369012)

> "Aimee Sinclair: the actress everyone thinks they know but can't remember where from. But I know exactly who you are. I know what you've done. And I am watching you.

> "When Aimee comes home and discovers her husband is missing, she doesn't seem to know what to do or how to act. The police think she's hiding something and they're right, she is – but perhaps not what they thought. Aimee has a secret she's never shared, and yet, she suspects that someone knows.

> "As she struggles to keep her career and sanity intact, her past comes back to haunt her in ways more dangerous than she could have ever imagined..."

## [Valley of Death, by Scott Mariani](https://suffolklibraries.overdrive.com/media/4538644?cid=1010720)

> "People going missing in the remote wilds of India is not unusual. But when the son of a wealthy Delhi businessman is kidnapped just weeks after his brother fell victim to an alleged bandit attack in the mountains of Haryana, it raises eyebrows. With the local police doing close to nothing, there's only one man for the job: ex-SAS major Ben Hope.

> "But for Ben, this is no ordinary rescue case. Because this plea for help is coming from a special person from his past, who now has nobody else to turn to. Ben's mission will take him into the heart of the arid Indian wilderness, pitting him against ruthless gangs and desperate men. But Ben is determined to save the day. Whatever it takes."

## [The Age of Decadence: Britain 1880 to 1914, by Simon Heffer](https://suffolklibraries.overdrive.com/media/3513592)

> 'The folk-memory of Britain in the years before the Great War is of a powerful, contented, orderly and thriving country. She commanded a vast empire. She bestrode international commerce. Her citizens were living longer, profiting from civil liberties their grandparents only dreamt of, and enjoying an expanding range of comforts and pastimes. The mood of pride and self-confidence is familiar from Elgar's Pomp and Circumstance marches, newsreels of George V's coronation and the London's great Edwardian palaces.

> "Yet things were very different below the surface. In The Age of Decadence Simon Heffer exposes the contradictions of late-Victorian and Edwardian Britain."

## [A Perfect Cornish Summer, by Phillipa Ashley](https://suffolklibraries.overdrive.com/media/4335338?cid=1010720)

> "Summer is on the horizon, and the people of Porthmellow are eagerly awaiting the annual food festival. At least, most of them are...

> "For Sam Lovell, organising the summer festival in her hometown is one of the highlights of her year. It's not always smooth sailing, but she loves to see Porthmellow's harbour packed with happy visitors, and being on the committee has provided a much-needed distraction from the drama in her family life (and the distinct lack of it in her love life).

> "When their star guest pulls out with only a few weeks to go, everyone's delighted when a London chef who grew up locally steps in at the last minute. But Gabe Matthias is the last person Sam was expecting to see, and his return to Porthmellow will change her quiet coastal life for ever."

## [Capture or Kill, by Tom Marcus](https://suffolklibraries.overdrive.com/media/3690995)

> "Matt Logan is an MI5 agent for the British government. Working on the frontline of counter-terrorism in the UK he's trained to protect its citizens against all threats.

> "When two brothers known operationally as 'Iron Sword' and 'Stone Fist' are suspected of plotting a major terrorist event, Logan and his team work undercover to track them down. If they fail, an attack will be unleashed that will rock the country to its very core.

> "Frustrated by always needing to obey the rules, Logan yearns for a way to break through the red tape that hinders their progress. His wishes seem to come true when he is offered the chance to join a new, deniable outfit known as 'Blindeye'.

> "Then devastating news reaches Logan, throwing his world into turmoil. But one thing remains certain: he will join the team and become their fiercest, most ruthless operative."

## [The Huntress, by Kate Quinn](https://suffolklibraries.overdrive.com/media/4581886)

> "On the icy edge of Soviet Russia, bold and reckless Nina Markova joins the infamous Night Witches – an all-female bomber regiment. But when she is downed behind enemy lines, Nina must use all her wits to survive her encounter with a lethal Nazi murderess known as the Huntress.

> "British war correspondent Ian Graham abandons journalism to become a Nazi hunter, yet one target eludes him: the Huntress. And Nina Markova is the only witness to escape her alive.

> "In post-war Boston, seventeen-year-old Jordan McBride is increasingly disquieted by the soft-spoken German widow who becomes her new stepmother. Delving into her past, Jordan slowly realizes that a Nazi killer may be hiding in plain sight."


text:
APP = mill-cli
DOCS = docs
GIT_HASH = $(shell git log -1 --pretty=format:"%H")

default: docs

docs:
	# generate doccs with docco
	@# !!! docco needs to be installed!
	docco -o ${DOCS} -l parallel ${APP}.js lib/build/mill-build.js lib/commands/output.js lib/alias.js lib/readProjectConfig.js lib/utils.js
	cp ${DOCS}/${APP}.html ${DOCS}/index.html

docs-push:
	# push docs to gh-pages
	@# !!! gh-pages clone needs to be in /${DOCS}!

	make docs

	cd ${DOCS} && git add --all
	cd ${DOCS} && git commit -m "./${DOCS} based on ${GIT_HASH}"
	cd ${DOCS} && git push origin gh-pages

# fool make, run this list of tasks no matter what
.PHONY: docs docs-push


text:
using FluentAssertions;
using Xunit;

namespace Eris.Packets.Test.PacketWriterTests
{
    public class WriteSeekTests
    {
        [Fact]
        public void Seek_Begin()
        {
            using (var writer = new PacketWriter())
            {
                writer.WriteUInt8(1);

                writer.Seek(0, System.IO.SeekOrigin.Begin);

                writer.WriteUInt8(2);

                var result = writer.GetBytes();

                result.Should().Equal(new byte[] { 2 });
            }
        }

        [Fact]
        public void Seek_Current()
        {
            using (var writer = new PacketWriter())
            {
                writer.WriteUInt8(1);

                writer.Seek(-1, System.IO.SeekOrigin.Current);

                writer.WriteUInt8(2);

                var result = writer.GetBytes();

                result.Should().Equal(new byte[] { 2 });
            }
        }

        [Fact]
        public void Seek_End()
        {
            using (var writer = new PacketWriter())
            {
                writer.WriteUInt8(1);

                writer.Seek(-1, System.IO.SeekOrigin.End);

                writer.WriteUInt8(2);

                var result = writer.GetBytes();

                result.Should().Equal(new byte[] { 2 });
            }
        }
    }
}


text:
package com.firebase.ui.auth.util;

import com.google.android.gms.auth.api.credentials.Credential;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.tasks.Task;

public interface CredentialTaskApi {
    Task<Status> disableAutoSignIn();

    Task<Status> delete(Credential credential);
}