示例#1
0
 private BaseNode CreateNode(string value)
 {
     if (!KirinArithmetic.IsArithmetic(value, out var result))
     {
         return new ValueNode()
                {
                    RawValue = value
                }
     }
     ;
     return(CreateNode(result));
 }
示例#2
0
        /// <summary>
        /// Evaluates raw FiM++ string into a value
        /// </summary>
        public static object Evaluate(
            FiMClass reportClass,
            string evaluatable,
            out KirinVariableType returnedType,
            KirinVariableType?expectedType = null
            )
        {
            returnedType = KirinVariableType.UNKNOWN;

            // Nothing
            if (evaluatable == "nothing" && expectedType != null)
            {
                returnedType = (KirinVariableType)expectedType;
                return(FiMHelper.GetDefaultValue(returnedType));
            }

            // Calling an existing variable
            if (reportClass.GetVariable(evaluatable) != null)
            {
                var variable = reportClass.GetVariable(evaluatable);
                returnedType = variable.Type;
                return(variable.Value);
            }

            // Calling an existing method
            if (reportClass.GetParagraphLazy(evaluatable) != null)
            {
                KirinValue[] args  = null;
                string       pName = evaluatable;

                if (pName.Contains(KirinFunctionCall.FunctionParam))
                {
                    int pIndex = pName.IndexOf(KirinFunctionCall.FunctionParam);
                    pName = pName.Substring(0, pIndex);
                    args  = KirinFunctionCall.ParseCallArguments(
                        evaluatable.Substring(pName.Length + KirinFunctionCall.FunctionParam.Length), reportClass
                        ).ToArray();
                }

                var paragraph = reportClass.GetParagraph(pName);
                if (paragraph == null)
                {
                    throw new FiMException("Paragraph " + pName + " not found");
                }

                if (paragraph.ReturnType == KirinVariableType.UNKNOWN)
                {
                    throw new FiMException("Paragraph returns nothing");
                }
                returnedType = paragraph.ReturnType;
                return(paragraph.Execute(args));
            }

            // Array
            if (expectedType != null && FiMHelper.IsTypeArray((KirinVariableType)expectedType))
            {
                System.Collections.IDictionary dict = null;
                var args = KirinFunctionCall.ParseCallArguments(evaluatable, reportClass);

                if (!FiMHelper.IsTypeOfArray(args[0].Type, (KirinArrayType)expectedType))
                {
                    throw new FiMException("Invalid list value type");
                }
                if (!args.All(a => a.Type == args[0].Type))
                {
                    throw new FiMException("Unidentical list value type");
                }

                int i = 1;
                if (expectedType == KirinVariableType.STRING_ARRAY)
                {
                    dict = new Dictionary <int, string>();
                    args.ForEach(kv => dict.Add(i++, Convert.ToString(kv.Value)));
                }
                else if (expectedType == KirinVariableType.NUMBER_ARRAY)
                {
                    dict = new Dictionary <int, double>();
                    args.ForEach(kv => dict.Add(i++, Convert.ToDouble(kv.Value)));
                }
                else if (expectedType == KirinVariableType.BOOL_ARRAY)
                {
                    dict = new Dictionary <int, bool>();
                    args.ForEach(kv => dict.Add(i++, Convert.ToBoolean(kv.Value)));
                }

                returnedType = (KirinVariableType)expectedType;
                return(dict);
            }

            // Array index
            if (FiMHelper.ArrayIndex.IsArrayIndex(evaluatable, reportClass))
            {
                var match = FiMHelper.ArrayIndex.GetArrayIndex(evaluatable, reportClass);

                var varIndex = new KirinValue(match.RawIndex, reportClass);
                if (varIndex.Type != KirinVariableType.NUMBER)
                {
                    throw new FiMException("Invalid index value");
                }
                int index = Convert.ToInt32(varIndex.Value);

                string strVar = match.RawVariable;
                if (!reportClass.Variables.Has(strVar))
                {
                    throw new FiMException("Variable " + strVar + " does not exist");
                }
                var variable = reportClass.Variables.Get(strVar);
                if (!FiMHelper.IsTypeArray(variable.Type) && variable.Type != KirinVariableType.STRING)
                {
                    throw new FiMException("Cannot index a non-array variable");
                }

                if (variable.Type == KirinVariableType.STRING)
                {
                    returnedType = KirinVariableType.CHAR;
                    return(Convert.ToString(variable.Value)[index - 1]);
                }

                var dict = variable.Value as System.Collections.IDictionary;
                if (variable.Type == KirinVariableType.STRING_ARRAY)
                {
                    returnedType = KirinVariableType.STRING;
                    return(Convert.ToString(dict[index]));
                }
                if (variable.Type == KirinVariableType.BOOL_ARRAY)
                {
                    returnedType = KirinVariableType.BOOL;
                    return(Convert.ToBoolean(dict[index]));
                }
                if (variable.Type == KirinVariableType.NUMBER_ARRAY)
                {
                    returnedType = KirinVariableType.NUMBER;
                    return(Convert.ToDouble(dict[index]));
                }
            }

            // Arithmetic
            if (KirinArithmetic.IsArithmetic(evaluatable, out var arithmeticResult))
            {
                var arithmetic = new KirinArithmetic(arithmeticResult);
                var value      = arithmetic.GetValue(reportClass);
                returnedType = FiMHelper.AsVariableType(value.GetType());
                return(value);
            }

            // Conditional
            if (KirinConditional.IsConditional(evaluatable, out var conditionalResult))
            {
                var conditional = new KirinConditional(conditionalResult);
                returnedType = KirinVariableType.BOOL;
                return(conditional.GetValue(reportClass));
            }

            throw new FiMException("Cannot evaluate " + evaluatable);
        }