예제 #1
0
        public override INumber Execute(RuntimeData runtime, params INumber[] parameters)
        {
            runtime.AddBlock(new BlockData());
            var res = parameters[1].Eval(runtime);

            res = res.Optimise(runtime);

            parameters[0].Eval(runtime);
            res = res.Eval(runtime);

            runtime.PopBlock();

            return(res);
        }
예제 #2
0
        /// <summary>
        /// 二次方程式を解決する
        /// </summary>
        private INumber SolutionQuadraticEquation(RuntimeData runtime, string varname, Dictionary <int, INumber> keisu)
        {
            if (!(keisu.Keys.Where(k => k >= 3).Count() == 0 &&                    // x^3のような大きなべき乗がない
                  keisu.Values.Where(v => !(v is IConstParameter)).Count() == 0 && // 係数が全て実数である
                  keisu.ContainsKey(2) &&                                          // x^2が含まれている
                  !(keisu[2] is Number && (keisu[2] as Number).Value == 0)))       // x^2の係数が0ではない
            {
                return(null);
            }

            runtime.AddLogWay("AsQuadraticEquation", keisu[2], keisu[1], keisu[0]);

            INumber res1 = null, res2 = null;

            try {
                runtime.AddBlock(new BlockData()
                {
                    MoreScope = false
                });
                runtime.NowBlock.Variables.Add("a", keisu[2]);
                runtime.NowBlock.Variables.Add("b", keisu[1]);
                runtime.NowBlock.Variables.Add("c", keisu[0]);

                // ( -b ± √(b^2 - 4ac)) / 2a
                res1 = (runtime.Setting.GetExpression("((0-b)+sqrt(b^2-4a*c))/(2a)") as IEval).Eval(runtime);
                res2 = (runtime.Setting.GetExpression("((0-b)-sqrt(b^2-4a*c))/(2a)") as IEval).Eval(runtime);

                var vr = new Variable(varname);
                runtime.AddLogWay("_QuadraticEquationWay1", vr, res1);
                runtime.AddLogWay("_QuadraticEquationWay2", vr, res2);
            }
            finally { runtime.PopBlock(); }

            if (res1 == null && res2 == null)
            {
                return(null);
            }

            Results ress = new Results(new Variable(varname));

            ress.items.Add(res1);
            if (!res1.Equals(runtime, res2))
            {
                ress.items.Add(res2);
            }
            return(ress);
        }
예제 #3
0
        public override INumber Execute(RuntimeData runtime, params INumber[] parameters)
        {
            if (this.name == "#userDefine")
            {
                throw new RuntimeException("この関数をそのまま呼び出すことはできません。");
            }


            runtime.AddBlock(new BlockData());

            for (int i = 0; i < parameters.Length; i++)
            {
                var exp = parameters[i];
                runtime.SetVariable(runtime,
                                    new Variable(new Token(this._paramName[i], Analyzer.TokenType.Member)),
                                    exp.Eval(runtime));
            }
            var res = this.formula.Eval(runtime);

            runtime.PopBlock();

            return(res);
        }
예제 #4
0
        public INumber Eval(RuntimeData runtime)
        {
            BlockData data = runtime.NowBlock;


            for (int i = 0; i < this.Count; i++)
            {
                IExpression exp = this.Items[i];

                if (exp is Operator)
                {
                    INumber  left = null, right = null;
                    Operator op = exp as Operator;

                    if (runtime.Setting.IsDebug)
                    {
                        // Console.Clear();
                        OutputStackData(runtime, exp);
                    }

                    bool willEval = true;
                    // 後ろの方にEvalせずに実行する演算子がある場合、変数を評価しないようにする
                    for (int j = i + 1; j < this.Count; j++)
                    {
                        if (this.items[j] is Operator &&
                            !(this.items[j] as Operator).Evaluator.DoEvaledParam)
                        {
                            willEval = false;
                            runtime.AddBlock(new BlockData()
                            {
                                MoreScope = false
                            });
                            if (runtime.Setting.IsDebug)
                            {
                                Console.WriteLine("AddBlock[MoreScope=false] しました");
                            }
                            break;
                        }
                    }

                    if (op.Evaluator.RequireRightParameter)
                    {
                        var r = data.Pop();
                        if (op.Evaluator.DoEvaledParam && willEval)
                        {
                            r = (r as IEval).Eval(runtime);
                        }
                        if (!op.Evaluator.DoEvaledParam && r is INumber)
                        {
                        }
                        else if (r is Variable || r is Member)
                        {
                        }
                        else if (r is Member)
                        {
                            r = (r as Member).GetVariable(runtime);
                        }
                        else
                        {
                            r = (r as IEval).Eval(runtime);
                        }
                        right = r as INumber;
                        if (op.Evaluator.DoEvaledParam && willEval)
                        {
                            right = right.Eval(runtime);
                        }
                    }
                    if (op.Evaluator.RequireLeftParameter)
                    {
                        var l = data.Pop();
                        if (op.Evaluator.DoEvaledParam && willEval)
                        {
                            l = (l as IEval).Eval(runtime);
                        }
                        if (!op.Evaluator.DoEvaledParam && l is INumber)
                        {
                        }
                        else if (l is Variable)
                        {
                        }
                        else if (l is Member)
                        {
                            l = (l as Member).GetVariable(runtime);
                        }
                        else
                        {
                            l = (l as IEval).Eval(runtime);
                        }

                        left = l as INumber;
                        if (op.Evaluator.DoEvaledParam && willEval)
                        {
                            left = left.Eval(runtime);
                        }
                    }

                    var res = (exp as Operator).Evaluator.Execute(runtime, left as INumber, right as INumber);
                    if (res != null && runtime.Setting.DoOptimize)
                    {
                        res = res.Optimise(runtime);
                    }

                    if (!willEval)
                    {
                        runtime.PopBlock();
                    }

                    data.Push(res);

                    if (runtime.Setting.IsDebug)
                    {
                        // Console.Clear();
                        Console.WriteLine("Eval RPE Formula : ({0})[{1}] {2} ({3})[{4}] => {5}[{6}]",
                                          left != null ? left.ToString() : "null",
                                          left != null ? left.GetType().Name : "",
                                          (exp as Operator).Evaluator.Name,
                                          right != null ? right.ToString() : "null",
                                          right != null ? right.GetType().Name : "",
                                          res != null ? res.ToString() : "null",
                                          res != null ? res.GetType().Name : "");
                        OutputStackData(runtime, null);
                    }
                }
                else
                {
                    if (exp is IEval)
                    {
                        data.Push(exp as IEval);
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                }
            }

            if (data.Count == 0)
            {
                return(null);
            }
            else
            {
                var result = data.Pop() as INumber;
                if (result != null && runtime.Setting.DoOptimize)
                {
                    return(result.Optimise(runtime));
                }
                return(result);
            }
        }
예제 #5
0
        public override INumber Eval(RuntimeData runtime)
        {
            // 1しかない場合は変数
            if (this.items.Count == 1)
            {
                if (!(this.items[0] is INumber))
                {
                    throw new NotImplementedException("FunctionFormulaに値以外が紛れ込んでいます");
                }
                return((this.items[0] as INumber).Eval(runtime));
            }

            bool        nextFlag = false;
            IExpression func     = null;
            INumber     multiple = Number.New(1);

            for (int i = 0; i < this.items.Count; i++)
            {
                IExpression ex = this.items[i];

                if (ex is Member &&
                    ((nextFlag && func != null) || (!nextFlag && func == null)))
                {
                    func = FunctionFormula.GetMember(runtime, func, ex as Member);
                    if (func == null)
                    {
                        throw new SyntaxException(string.Format("'{0}'は見つかりませんでした", ex.Token.Text), ex.Token,
                                                  new KeyNotFoundException());
                    }
                    if (func is INumber && !(func is IEvalWithParameters))
                    {
                        multiple = multiple.Multiple(runtime, func as INumber);
                        func     = null;
                    }
                    nextFlag = false;
                    continue;
                }
                if (ex is Operator &&
                    ex.Token.Text == runtime.Setting.Spec.ScopeOperator)
                {
                    nextFlag = true;
                    continue;
                }
                // パラメータ関係
                if ((ex is IFormula) && !nextFlag)
                {
                    if (func == null && multiple is IEvalWithParameters)
                    {
                        func     = multiple;
                        multiple = Number.New(1);
                    }

                    if (func != null)
                    {
                        runtime.AddBlock(new BlockData()
                        {
                            MoreScope = true
                        });
                        runtime.NowBlock.Push(new LineBreak());

                        (ex as IFormula).ExecuteAsParameter(runtime);

                        IExpression res = null;
                        if (func is INumber && func is IEvalWithParameters)
                        {
                            List <INumber> prm = new List <INumber>();
                            for (; runtime.NowBlock.Stack.Length != 0;)
                            {
                                var it = runtime.NowBlock.Pop(); if (it is LineBreak)
                                {
                                    continue;
                                }
                                if (!(it is INumber))
                                {
                                    throw new RuntimeException("インデックス指定で値型(INumber)以外のパラメータを指定することはできません。", it);
                                }
                                prm.Add(it as INumber);
                            }
                            res = (func as IEvalWithParameters).Execute(runtime, prm.ToArray()) as IExpression;
                        }
                        else
                        {
                            res = ExecuteFunc(runtime, func, multiple);
                        }

                        runtime.PopBlock();

                        if (res is INumber)
                        {
                            if (multiple is Number && (multiple as Number).Value != 1)
                            {
                                multiple = multiple.Multiple(runtime, res as INumber);
                            }
                            else
                            {
                                multiple = res as INumber;
                            }
                            func = null;
                        }
                        else if (res == null)
                        {
                            func     = null;
                            multiple = null;
                        }
                        else
                        {
                            func = res;
                            throw new NotImplementedException("関数の戻り値は現在 '値' しか対応していません");
                        }

                        continue;
                    }
                    else
                    {
                        if (multiple.Equals(runtime, Number.New(1)))
                        {
                            return(this); // 未解決のメンバーを実行しようとしている式は評価せずに返す
                        }
                        else
                        {
                            var res = (ex as IFormula).Eval(runtime);
                            multiple = multiple.Multiple(runtime, res);
                        }
                        continue;
                    }
                }

                throw new NotImplementedException();
            }

            if (func == null && multiple == null)
            {
                return(null);
            }
            if (func == null)
            {
                return(multiple);
            }
            if (!(func is INumber))
            {
                throw new RuntimeException("現在、関数の戻り値は値のみに対応しています。関数ポインターを戻り値にすることはできません。", this);
            }


            return((func as INumber).Eval(runtime));
        }