예제 #1
0
        public object Execute(FiMClass reportClass, bool global = false)
        {
            if (reportClass.GetVariable(this.Name) != null)
            {
                throw new FiMException("Variable " + this.Name + " already exists");
            }

            KirinValue value = new KirinValue(this.RawValue, reportClass, this.ExpectedType);

            if (value.Value == null)
            {
                value.Value = FiMHelper.GetDefaultValue(this.ExpectedType);
            }
            else
            {
                if (value.Type != this.ExpectedType)
                {
                    throw new FiMException("Expected " + this.ExpectedType.AsNamedString() +
                                           ", got " + value.Type.AsNamedString());
                }
            }
            value.Constant = Constant;

            FiMVariable var = new FiMVariable(this.Name, value);

            reportClass.Variables.Push(var, global);
            return(null);
        }
예제 #2
0
        public override object Execute(FiMClass reportClass, params object[] args)
        {
            int localVariables = 0;

            reportClass.Variables.PushFunctionStack();

            if (this.Arguments?.Count() > 0)
            {
                for (int i = 0; i < this.Arguments.Count(); i++)
                {
                    if (reportClass.Variables.Has(this.Arguments[i].Name))
                    {
                        throw new FiMException("Variable name " + this.Arguments[i].Name + " already exists");
                    }

                    if (i < args.Length)
                    {
                        if (FiMHelper.AsVariableType(args[i]) != this.Arguments[i].Type)
                        {
                            throw new FiMException("Expected " + this.Arguments[i].Type.AsNamedString()
                                                   + ", got " + FiMHelper.AsVariableType(args[i]).AsNamedString());
                        }

                        reportClass.Variables.Push(new FiMVariable(this.Arguments[i].Name, new KirinValue(args[i])));
                    }
                    else
                    {
                        reportClass.Variables.Push(
                            new FiMVariable(
                                this.Arguments[i].Name,
                                new KirinValue(FiMHelper.GetDefaultValue(this.Arguments[i].Type))
                                )
                            );
                    }
                    localVariables++;
                }
            }

            var result = Statement.Execute(reportClass);

            reportClass.Variables.PopFunctionStack();

            if (result != null && this.Returns == null)
            {
                throw new FiMException("Non-value returning function returned value");
            }
            if (result != null && this.Returns != null && this.Returns != KirinVariableType.UNKNOWN)
            {
                if (FiMHelper.AsVariableType(result) != this.Returns)
                {
                    throw new FiMException("Expected " + ((KirinVariableType)this.Returns).AsNamedString()
                                           + ", got " + FiMHelper.AsVariableType(result).AsNamedString());
                }

                return(result);
            }

            return(null);
        }
예제 #3
0
        public override object Execute(FiMClass reportClass, params object[] args)
        {
            object[] sanitizedArgs = null;
            if (this.Arguments?.Count > 0)
            {
                sanitizedArgs = new object[this.Arguments.Count];
                for (int i = 0; i < this.Arguments.Count; i++)
                {
                    if (i < args.Length)
                    {
                        if (this.Arguments[i] == KirinVariableType.EXPERIMENTAL_DYNAMIC_ARRAY)
                        {
                            if (!FiMHelper.IsTypeArray(args[i]))
                            {
                                throw new FiMException("Expected an array, got " + FiMHelper.AsVariableType(args[i]).AsNamedString());
                            }
                        }
                        else if (FiMHelper.AsVariableType(args[i]) != this.Arguments[i])
                        {
                            throw new FiMException("Expected " + this.Arguments[i].AsNamedString() + ", got " + FiMHelper.AsVariableType(args[i]).AsNamedString());
                        }
                        sanitizedArgs[i] = args[i];
                    }
                    else
                    {
                        sanitizedArgs[i] = FiMHelper.GetDefaultValue(this.Arguments[i]);
                    }
                }
            }

            object result;

            try
            {
                result = this.Function.DynamicInvoke(sanitizedArgs);
            }
            catch (Exception ex)
            {
                throw new Exception("An error has occured while running a custom method\n\n" + ex.ToString());
            }

            if (result != null && this.Returns == null)
            {
                throw new FiMException("Non-value returning function returned value");
            }
            if (result != null && this.Returns != null && this.Returns != KirinVariableType.UNKNOWN)
            {
                if (FiMHelper.AsVariableType(result) != this.Returns)
                {
                    throw new FiMException("Expected " + ((KirinVariableType)this.Returns).AsNamedString()
                                           + ", got " + FiMHelper.AsVariableType(result).AsNamedString());
                }

                return(result);
            }

            return(null);
        }
예제 #4
0
        public KirinValue Load()
        {
            if (this.Raw == null)
            {
                if (FiMHelper.IsTypeArray(this.Type))
                {
                    this._Value = FiMHelper.GetDefaultValue(this.Type);
                }
                else
                {
                    if (this.ForcedType == null)
                    {
                        throw new FiMException("Value is null");
                    }
                    this._Value = FiMHelper.GetDefaultValue((KirinVariableType)this.ForcedType);
                }
            }
            else
            {
                string raw = this.Raw;

                var eType = FiMHelper.DeclarationType.Determine(" " + raw, out string eKeyword, false);
                if (eType != KirinVariableType.UNKNOWN)
                {
                    raw = raw.Substring(eKeyword.Length);
                    this.ForceType(eType);
                }

                if (this.ForcedType != null)
                {
                    eType = (KirinVariableType)this.ForcedType;
                }

                object value;
                if (KirinLiteral.TryParse(raw, out object lResult))
                {
                    value = lResult;
                }
                else
                {
                    value = KirinValue.Evaluate(Class, raw, out var returnedType, ForcedType);
                    this.ForceType(returnedType);
                }

                if (eType != KirinVariableType.UNKNOWN && FiMHelper.AsVariableType(value) != eType)
                {
                    throw new FiMException("Expected " + eType.AsNamedString() + ", got " + FiMHelper.AsVariableType(value));
                }
                this._Value = value;
            }
            return(this);
        }
예제 #5
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);
        }