public IExpression EvaluateGenericElement(EvaluationParameters parameters, Nodes.GenericElement element)
        {
            GenericTagEvaluator eval;

            _GenericTagEvaluators.TryGetValue(element.Tag, out eval);
            return((eval ?? DefaultGenericTagEvaluator)(parameters, element));
        }
        protected virtual IExpression EvaluateSheet(EvaluationParameters parameters, Nodes.GenericElement element)
        {
            IExpression[] evalArgs = element.Arguments.Select(_ => _.TryEvaluate(parameters)).ToArray();
            if (evalArgs.Length < 2)
            {
                throw new InvalidOperationException();
            }
            string sheetName = evalArgs[0].ToString();
            int    rowKey    = ToInteger(evalArgs[1]);
            int    colKey    = 0;

            if (evalArgs.Length > 2)
            {
                colKey = ToInteger(evalArgs[2]);
            }

            XivRow row   = Data.GetSheet(sheetName)[rowKey];
            object value = row[colKey];

            if (value is INode)
            {
                EvaluationParameters innerParams = new EvaluationParameters(parameters);
                innerParams.InputParameters.Clear();
                for (int i = 3; i < evalArgs.Length; ++i)
                {
                    innerParams.InputParameters[i - 2] = evalArgs[i];
                }


                value = EvaluationHelper.TryEvaluate((INode)value, innerParams);
            }

            return(new GenericExpression(new ObjectWithDisplay(value, row)));
        }
        protected virtual IExpression EvaluateTime(EvaluationParameters parameters, Nodes.GenericElement element)
        {
            /* Appears to set values for an input time.
             * - 222 / DEh  Year
             * - 221 / DDh  Month
             * - 220 / DCh  Day of week
             * - 219 / DBh  Day of month
             * - 218 / DAh  Hour
             * - 217 / D9h  Minute
             */

            IExpression argEval = element.Arguments.First().TryEvaluate(parameters);
            int         argInt  = ToInteger(argEval);

            DateTime utcTime   = EorzeaDateTime.Zero.AddSeconds(argInt);
            DateTime localTime = utcTime.ToLocalTime();

            parameters.TopLevelParameters[0xDE] = localTime.Year;
            parameters.TopLevelParameters[0xDD] = localTime.Month;
            parameters.TopLevelParameters[0xDC] = 1 + (int)localTime.DayOfWeek;
            parameters.TopLevelParameters[0xDB] = localTime.Day;
            parameters.TopLevelParameters[0xDA] = localTime.Hour;
            parameters.TopLevelParameters[0xD9] = localTime.Minute;

            return(GenericExpression.Empty);
        }
        protected virtual IExpression EvaluateSheetWithAttributive(EvaluationParameters parameters, Nodes.GenericElement element)
        {
            IExpression[] evalArgs = element.Arguments.Select(_ => _.TryEvaluate(parameters)).ToArray();
            if (evalArgs.Length < 3)
            {
                throw new InvalidOperationException();
            }

            Ex.Language lang = TagToLanguageMap[element.Tag];

            string sheetName         = evalArgs[0].ToString();
            int    attributiveRowKey = ToInteger(evalArgs[1]);
            int    rowKey            = ToInteger(evalArgs[2]);

            int columnKey = 0;

            if (evalArgs.Length > 3)
            {
                columnKey = ToInteger(evalArgs[3]);
            }

            int attributiveColumnKey = AttributiveColumnOffsets[element.Tag];

            if (evalArgs.Length > 4)
            {
                attributiveColumnKey += ToInteger(evalArgs[4]);
            }

            XivRow row = Data.GetSheet(sheetName)[rowKey];
            object value;

            if (row is Ex.IMultiRow)
            {
                value = ((Ex.IMultiRow)row)[columnKey, lang];
            }
            else
            {
                value = row[columnKey];
            }

            XivRow attributiveRow = Data.GetSheet(AttributiveSheetName)[attributiveRowKey];
            object attributiveValue;

            if (attributiveRow is Ex.IMultiRow)
            {
                attributiveValue = ((Ex.IMultiRow)attributiveRow)[attributiveColumnKey, lang];
            }
            else
            {
                attributiveValue = attributiveRow[attributiveColumnKey];
            }

            EvaluationParameters innerParams = new EvaluationParameters(parameters);

            innerParams.InputParameters.Clear();
            for (int i = 5; i < evalArgs.Length; ++i)
            {
                innerParams.InputParameters[i - 2] = evalArgs[i];
            }

            if (value is INode)
            {
                value = EvaluationHelper.TryEvaluate((INode)value, innerParams);
            }
            if (attributiveValue is INode)
            {
                attributiveValue = EvaluationHelper.TryEvaluate((INode)attributiveValue, innerParams);
            }

            return(new SurroundedExpression(new ObjectWithDisplay(attributiveValue, attributiveRow), new ObjectWithDisplay(value, row), null));
        }
        protected virtual IExpression EvaluateZeroPaddedValue(EvaluationParameters parameters, Nodes.GenericElement element)
        {
            IExpression lenEval = element.Arguments.First().TryEvaluate(parameters);
            int         len     = ToInteger(lenEval);
            IExpression eval    = element.Content.TryEvaluate(parameters);
            int         intVal  = ToInteger(eval);

            return(new GenericExpression(intVal.ToString("D" + len.ToString())));
        }
        protected virtual IExpression EvaluateTwoDigitValue(EvaluationParameters parameters, Nodes.GenericElement element)
        {
            IExpression eval   = element.Content.TryEvaluate(parameters);
            int         intVal = ToInteger(eval);

            return(new GenericExpression(intVal.ToString("D2")));
        }