protected override SyntaxToken VisitFunction(FunctionSyntaxToken token) { SyntaxToken arg = token.Arguments[0]; SyntaxToken diff = this.Visit(arg); SyntaxToken one = SyntaxToken.Constant(1); SyntaxToken two = SyntaxToken.Constant(2); SyntaxToken result; switch (token.Type) { case FunctionType.Sin: result = SyntaxToken.Cos(arg); break; case FunctionType.Cos: result = SyntaxToken.Negate(SyntaxToken.Sin(arg)); break; case FunctionType.Tan: result = SyntaxToken.Add(one, SyntaxToken.Pow(SyntaxToken.Tan(arg), two)); break; case FunctionType.Cot: result = SyntaxToken.Negate(SyntaxToken.Add(one, SyntaxToken.Pow(SyntaxToken.Cot(arg), two))); break; case FunctionType.Asin: result = SyntaxToken.Divide(one, SyntaxToken.Root(SyntaxToken.Subtract(one, SyntaxToken.Pow(arg, two)), two)); break; case FunctionType.Acos: result = -(one / SyntaxToken.Root(one - SyntaxToken.Pow(arg, two), two)); break; case FunctionType.Atan: result = one / (one + SyntaxToken.Pow(arg, two)); break; case FunctionType.Acot: result = -(one / (one + SyntaxToken.Pow(arg, two))); break; case FunctionType.Log: SyntaxToken b = token.Arguments[1]; result = one / (arg * SyntaxToken.Ln(b)); break; case FunctionType.Ln: result = one / arg; break; case FunctionType.Abs: result = arg / SyntaxToken.Abs(arg); break; case FunctionType.Unsupported: default: throw new NotSupportedException(); } return(result * diff); }
protected override SyntaxToken VisitBinary(BinarySyntaxToken token) { SyntaxToken left = this.Visit(token.Left); SyntaxToken right = this.Visit(token.Right); BinaryOperationType type = token.Type; if (left.TokenType == SyntaxTokenType.Constant && right.TokenType == SyntaxTokenType.Constant) { return this.EvalBinary((ConstantSyntaxToken)left, (ConstantSyntaxToken)right, type); } // swap constant to the right if ((type == BinaryOperationType.Add || type == BinaryOperationType.Multiply) && (left.TokenType == SyntaxTokenType.Constant)) { SyntaxToken temp = right; right = left; left = temp; } // add if (type == BinaryOperationType.Add) { if (right.HasValue(0)) { return left; } } // subtract else if (type == BinaryOperationType.Subtract) { if (right.HasValue(0)) { return left; } if (SyntaxToken.Equals(left, right)) { return SyntaxToken.Constant(0); } } // multiply else if (type == BinaryOperationType.Multiply) { if (right.HasValue(0)) { return SyntaxToken.Constant(0); } if (right.HasValue(1)) { return left; } if (left.TokenType == SyntaxTokenType.Binary && right.TokenType == SyntaxTokenType.Binary) { BinarySyntaxToken bl = (BinarySyntaxToken)left; BinarySyntaxToken br = (BinarySyntaxToken)right; if (bl.Type == BinaryOperationType.Power && br.Type == BinaryOperationType.Power && SyntaxToken.Equals(bl.Left, br.Left)) { return this.Visit(SyntaxToken.Pow(bl.Left, SyntaxToken.Add(bl.Right, br.Right))); } } } // divide else if (type == BinaryOperationType.Divide) { if (left.HasValue(0)) { return SyntaxToken.Constant(0); } if (SyntaxToken.Equals(left, right)) { return SyntaxToken.Constant(1); } } // modulus else if (type == BinaryOperationType.Modulus) { if (left.HasValue(0)) { return SyntaxToken.Constant(0); } if (SyntaxToken.Equals(left, right)) { return SyntaxToken.Constant(0); } } // pow else if (type == BinaryOperationType.Power) { if (right.HasValue(0)) { return SyntaxToken.Constant(1); } if (right.HasValue(1)) { return left; } if (left.HasValue(0)) { return SyntaxToken.Constant(1); } if (left.TokenType == SyntaxTokenType.Binary) { BinarySyntaxToken bl = (BinarySyntaxToken)left; if (bl.Type == BinaryOperationType.Power) { return this.Visit(SyntaxToken.Pow(bl.Left, SyntaxToken.Multiply(bl.Right, right))); } } } return SyntaxToken.Binary(left, right, type); }