private ValueFactory GetFactory(ExtraTypeIdContainer idContainer) { return(new ValueFactory(idContainer)); }
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); }
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); }
internal ValueFactory(ExtraTypeIdContainer idContainer) { _idContainer = idContainer; }