Beispiel #1
0
 private ValueFactory GetFactory(ExtraTypeIdContainer idContainer)
 {
     return(new ValueFactory(idContainer));
 }
Beispiel #2
0
        private InternalEvaluatorValue CalcInternal(List <BaseFormulaNode> nodes, VariablesSource variables, ExtraTypeIdContainer idContainer)
        {
            // If no nodes return default value
            if (nodes.Count == 0)
            {
                return(double.NaN);
            }

            // Rent stack
            var stack = _stackPool.Get();

            // Prevent dirty collection
            if (stack.Count > 0)
            {
                stack.Clear();
            }

            var factory = GetFactory(idContainer);

            for (int i = 0; i < nodes.Count; i++)
            {
                var node = nodes[i];

                if (node.TypeKey == NodeTypeEnum.Variable)
                {
                    var variableNode = (VariableNode)node;
                    var argumentVal  = variables.GetValue(variableNode.Name);

                    var val = factory.Create(argumentVal);
                    if (variableNode.IsNegative && val.IsNumber)
                    {
                        val = val.Number * -1;
                    }

                    stack.Push(val);
                }
                else if (node.TypeKey == NodeTypeEnum.Operator)
                {
                    var mathOperationNode = (OperatorNode)node;
                    InternalEvaluatorValue a;
                    InternalEvaluatorValue b;

                    switch (mathOperationNode.OperatorKey)
                    {
                    // Math
                    case Operator.Multiply: stack.Push(stack.Pop() * stack.Pop()); break;

                    case Operator.Divide:
                        a = stack.Pop();
                        b = stack.Pop();
                        stack.Push(b / a); break;

                    case Operator.Plus:
                        a = stack.Pop();
                        b = stack.Pop();

                        if (a.IsWord || b.IsWord)
                        {
                            stack.Push(factory.Word().Concat(b, a));
                        }
                        else if (a.IsNumber && b.IsDateTime)
                        {
                            stack.Push(factory.DateTime().Create(b.GetDateTime().AddDays(a.Number)));
                        }
                        else if (a.IsDateTime && b.IsNumber)
                        {
                            stack.Push(factory.DateTime().Create(a.GetDateTime().AddDays(b.Number)));
                        }
                        else
                        {
                            stack.Push(a + b);
                        }

                        break;

                    case Operator.Minus:
                        a = stack.Pop();
                        b = stack.Pop();

                        if (a.IsNumber && b.IsDateTime)
                        {
                            stack.Push(factory.DateTime().Create(b.GetDateTime().AddDays(-a.Number)));
                        }
                        else if (a.IsDateTime && b.IsDateTime)
                        {
                            stack.Push(b.GetDateTime().Subtract(a.GetDateTime()).TotalDays);
                        }
                        else
                        {
                            stack.Push(b - a);
                        }

                        break;

                    case Operator.Power:
                        a = stack.Pop();
                        b = stack.Pop();
                        stack.Push(Math.Pow(b, a)); break;

                    // Logic
                    case Operator.Less:
                        a = stack.Pop();
                        b = stack.Pop();
                        stack.Push(b < a ? 1 : 0); break;

                    case Operator.LessEqual:
                        a = stack.Pop();
                        b = stack.Pop();
                        stack.Push(b <= a ? 1 : 0); break;

                    case Operator.More:
                        a = stack.Pop();
                        b = stack.Pop();
                        stack.Push(b > a ? 1 : 0); break;

                    case Operator.MoreEqual:
                        a = stack.Pop();
                        b = stack.Pop();
                        stack.Push(b >= a ? 1 : 0); break;

                    case Operator.Equal:
                        a = stack.Pop();
                        b = stack.Pop();
                        stack.Push(Math.Abs(b - a) < NoStringEvaluatorConstants.FloatingTolerance ? 1 : 0); break;

                    case Operator.NotEqual:
                        a = stack.Pop();
                        b = stack.Pop();
                        stack.Push(Math.Abs(b - a) > NoStringEvaluatorConstants.FloatingTolerance ? 1 : 0); break;

                    // Additional logic
                    case Operator.And:
                        a = stack.Pop();
                        b = stack.Pop();
                        stack.Push(Math.Abs(a) > NoStringEvaluatorConstants.FloatingTolerance && Math.Abs(b) > NoStringEvaluatorConstants.FloatingTolerance ? 1 : 0); break;

                    case Operator.Or:
                        a = stack.Pop();
                        b = stack.Pop();
                        stack.Push(Math.Abs(a) > NoStringEvaluatorConstants.FloatingTolerance || Math.Abs(b) > NoStringEvaluatorConstants.FloatingTolerance ? 1 : 0); break;
                    }
                }
                else if (node.TypeKey == NodeTypeEnum.FunctionWrapper)
                {
                    var functionWrapper = (FunctionWrapperNode)node;
                    var functionVal     = CalcFunction(functionWrapper, variables, idContainer);

                    stack.Push(functionVal);
                }
                else if (node.TypeKey == NodeTypeEnum.Number)
                {
                    var valNode = (NumberNode)node;
                    stack.Push(valNode.Number);
                }
                else if (node.TypeKey == NodeTypeEnum.Word)
                {
                    var wordNode = (WordNode)node;
                    var wordItem = factory.Word().Create(wordNode.Word);

                    stack.Push(wordItem);
                }
                else if (node.TypeKey == NodeTypeEnum.WordList)
                {
                    var wordListNode = (WordListNode)node;
                    var wordListItem = factory.WordList().Create(wordListNode.WordList);

                    stack.Push(wordListItem);
                }
                else if (node.TypeKey == NodeTypeEnum.NumberList)
                {
                    var numberListNode = (NumberListNode)node;
                    var numberListItem = factory.NumberList().Create(numberListNode.NumberList);

                    stack.Push(numberListItem);
                }
            }

            // Result
            var res = stack.Pop();

            // Return to a pool
            _stackPool.Return(stack);

            return(res);
        }
Beispiel #3
0
        private InternalEvaluatorValue CalcFunction(FunctionWrapperNode functionWrapper, VariablesSource variables, ExtraTypeIdContainer idContainer)
        {
            var args = _argsPool.Get();

            // Prevent dirty collection
            if (args.Count > 0)
            {
                args.Clear();
            }

            for (int i = 0; i < functionWrapper.FunctionArgumentNodes.Count; i++)
            {
                var subNodes = functionWrapper.FunctionArgumentNodes[i];
                var subRes   = CalcInternal(subNodes, variables, idContainer);
                args.Add(subRes);
            }

            var factory = GetFactory(idContainer);
            var res     = functionWrapper.FunctionNode.Function.Execute(args, factory);

            if (functionWrapper.FunctionNode.IsNegative && res.IsNumber)
            {
                res = res.Number * -1;
            }

            // Clear collection
            args.Clear();

            // Return to a pool
            _argsPool.Return(args);

            return(res);
        }
Beispiel #4
0
 internal ValueFactory(ExtraTypeIdContainer idContainer)
 {
     _idContainer = idContainer;
 }