| using System; | 
| using System.Collections.Generic; | 
| using System.Linq; | 
| using System.Text; | 
| using Jace.Operations; | 
| using Jace.Execution; | 
|   | 
| namespace Jace | 
| { | 
|     public class Optimizer | 
|     { | 
|         private readonly IExecutor executor; | 
|   | 
|         public Optimizer(IExecutor executor) | 
|         { | 
|             this.executor = executor; | 
|         } | 
|   | 
|         public Operation Optimize(Operation operation, IFunctionRegistry functionRegistry, IConstantRegistry constantRegistry) | 
|         { | 
|             if (!operation.DependsOnVariables && operation.IsIdempotent && operation.GetType() != typeof(IntegerConstant) | 
|                 && operation.GetType() != typeof(FloatingPointConstant)) | 
|             { | 
|                 double result = executor.Execute(operation, functionRegistry, constantRegistry); | 
|                 return new FloatingPointConstant(result); | 
|             } | 
|             else | 
|             { | 
|                 if (operation.GetType() == typeof(Addition)) | 
|                 { | 
|                     Addition addition = (Addition)operation; | 
|                     addition.Argument1 = Optimize(addition.Argument1, functionRegistry, constantRegistry); | 
|                     addition.Argument2 = Optimize(addition.Argument2, functionRegistry, constantRegistry); | 
|                 } | 
|                 else if (operation.GetType() == typeof(Subtraction)) | 
|                 { | 
|                     Subtraction substraction = (Subtraction)operation; | 
|                     substraction.Argument1 = Optimize(substraction.Argument1, functionRegistry, constantRegistry); | 
|                     substraction.Argument2 = Optimize(substraction.Argument2, functionRegistry, constantRegistry); | 
|                 } | 
|                 else if (operation.GetType() == typeof(Multiplication)) | 
|                 { | 
|                     Multiplication multiplication = (Multiplication)operation; | 
|                     multiplication.Argument1 = Optimize(multiplication.Argument1, functionRegistry, constantRegistry); | 
|                     multiplication.Argument2 = Optimize(multiplication.Argument2, functionRegistry, constantRegistry); | 
|   | 
|                     if ((multiplication.Argument1.GetType() == typeof(FloatingPointConstant) && ((FloatingPointConstant)multiplication.Argument1).Value == 0.0) | 
|                         || (multiplication.Argument2.GetType() == typeof(FloatingPointConstant) && ((FloatingPointConstant)multiplication.Argument2).Value == 0.0)) | 
|                     { | 
|                         return new FloatingPointConstant(0.0); | 
|                     } | 
|                 } | 
|                 else if (operation.GetType() == typeof(Division)) | 
|                 { | 
|                     Division division = (Division)operation; | 
|                     division.Dividend = Optimize(division.Dividend, functionRegistry, constantRegistry); | 
|                     division.Divisor = Optimize(division.Divisor, functionRegistry, constantRegistry); | 
|                 } | 
|                 else if (operation.GetType() == typeof(Exponentiation)) | 
|                 { | 
|                     Exponentiation division = (Exponentiation)operation; | 
|                     division.Base = Optimize(division.Base, functionRegistry, constantRegistry); | 
|                     division.Exponent = Optimize(division.Exponent, functionRegistry, constantRegistry); | 
|                 } | 
|                 else if(operation.GetType() == typeof(Function)) | 
|                 { | 
|                     Function function = (Function)operation; | 
|                     IList<Operation> arguments = function.Arguments.Select(a => Optimize(a, functionRegistry, constantRegistry)).ToList(); | 
|                     function.Arguments = arguments; | 
|                 } | 
|   | 
|                 return operation; | 
|             } | 
|         } | 
|     } | 
| } |