private void VerifyResultStack() { if (resultStack.Count > 1) { Operation[] operations = resultStack.ToArray(); for (int i = 1; i < operations.Length; i++) { Operation operation = operations[i]; if (operation.GetType() == typeof(IntegerConstant)) { IntegerConstant constant = (IntegerConstant)operation; throw new ParseException(string.Format("Unexpected integer constant \"{0}\" found.", constant.Value)); } else if (operation.GetType() == typeof(FloatingPointConstant)) { FloatingPointConstant constant = (FloatingPointConstant)operation; throw new ParseException(string.Format("Unexpected floating point constant \"{0}\" found.", constant.Value)); } } throw new ParseException("The syntax of the provided formula is not valid."); } }
private string GetLabelText(Operation operation) { Type operationType = operation.GetType(); string name = operationType.Name; string dataType = "" + operation.DataType; string value = ""; IntegerConstant integerConstant = operation as IntegerConstant; if (integerConstant != null) { value = "(" + integerConstant.Value + ")"; } else { FloatingPointConstant floatingPointConstant = operation as FloatingPointConstant; if (floatingPointConstant != null) { value = "(" + floatingPointConstant.Value + ")"; } else { Variable variable = operation as Variable; if (variable != null) { value = "(" + variable.Name + ")"; } else { Function function = operation as Function; if (function != null) { value = "(" + function.FunctionName + ")"; } } } } return(string.Format(CultureInfo.InvariantCulture, "{0}<{1}>{2}", name, dataType, value)); }
private void GenerateMethodBody(ILGenerator generator, Operation operation, IFunctionRegistry functionRegistry) { if (operation == null) { throw new ArgumentNullException("operation"); } if (operation.GetType() == typeof(IntegerConstant)) { IntegerConstant constant = (IntegerConstant)operation; generator.Emit(OpCodes.Ldc_I4, constant.Value); generator.Emit(OpCodes.Conv_R8); } else if (operation.GetType() == typeof(FloatingPointConstant)) { FloatingPointConstant constant = (FloatingPointConstant)operation; generator.Emit(OpCodes.Ldc_R8, constant.Value); } else if (operation.GetType() == typeof(Variable)) { Type dictionaryType = typeof(IDictionary <string, double>); Variable variable = (Variable)operation; Label throwExceptionLabel = generator.DefineLabel(); Label returnLabel = generator.DefineLabel(); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Callvirt, typeof(FormulaContext).GetProperty("Variables").GetGetMethod()); generator.Emit(OpCodes.Ldstr, variable.Name); generator.Emit(OpCodes.Ldloca_S, (byte)0); generator.Emit(OpCodes.Callvirt, dictionaryType.GetMethod("TryGetValue", new Type[] { typeof(string), typeof(double).MakeByRefType() })); generator.Emit(OpCodes.Ldc_I4_0); generator.Emit(OpCodes.Ceq); generator.Emit(OpCodes.Brtrue_S, throwExceptionLabel); generator.Emit(OpCodes.Ldloc_0); generator.Emit(OpCodes.Br_S, returnLabel); generator.MarkLabel(throwExceptionLabel); generator.Emit(OpCodes.Ldstr, string.Format("The variable \"{0}\" used is not defined.", variable.Name)); generator.Emit(OpCodes.Newobj, typeof(VariableNotDefinedException).GetConstructor(new Type[] { typeof(string) })); generator.Emit(OpCodes.Throw); generator.MarkLabel(returnLabel); } else if (operation.GetType() == typeof(Multiplication)) { Multiplication multiplication = (Multiplication)operation; GenerateMethodBody(generator, multiplication.Argument1, functionRegistry); GenerateMethodBody(generator, multiplication.Argument2, functionRegistry); generator.Emit(OpCodes.Mul); } else if (operation.GetType() == typeof(Addition)) { Addition addition = (Addition)operation; GenerateMethodBody(generator, addition.Argument1, functionRegistry); GenerateMethodBody(generator, addition.Argument2, functionRegistry); generator.Emit(OpCodes.Add); } else if (operation.GetType() == typeof(Subtraction)) { Subtraction addition = (Subtraction)operation; GenerateMethodBody(generator, addition.Argument1, functionRegistry); GenerateMethodBody(generator, addition.Argument2, functionRegistry); generator.Emit(OpCodes.Sub); } else if (operation.GetType() == typeof(Division)) { Division division = (Division)operation; GenerateMethodBody(generator, division.Dividend, functionRegistry); GenerateMethodBody(generator, division.Divisor, functionRegistry); generator.Emit(OpCodes.Div); } else if (operation.GetType() == typeof(Modulo)) { Modulo modulo = (Modulo)operation; GenerateMethodBody(generator, modulo.Dividend, functionRegistry); GenerateMethodBody(generator, modulo.Divisor, functionRegistry); generator.Emit(OpCodes.Rem); } else if (operation.GetType() == typeof(Exponentiation)) { Exponentiation exponentation = (Exponentiation)operation; GenerateMethodBody(generator, exponentation.Base, functionRegistry); GenerateMethodBody(generator, exponentation.Exponent, functionRegistry); generator.Emit(OpCodes.Call, typeof(Math).GetMethod("Pow")); } else if (operation.GetType() == typeof(UnaryMinus)) { UnaryMinus unaryMinus = (UnaryMinus)operation; GenerateMethodBody(generator, unaryMinus.Argument, functionRegistry); generator.Emit(OpCodes.Neg); } else if (operation.GetType() == typeof(LessThan)) { LessThan lessThan = (LessThan)operation; Label ifLabel = generator.DefineLabel(); Label endLabel = generator.DefineLabel(); GenerateMethodBody(generator, lessThan.Argument1, functionRegistry); GenerateMethodBody(generator, lessThan.Argument2, functionRegistry); generator.Emit(OpCodes.Blt_S, ifLabel); generator.Emit(OpCodes.Ldc_R8, 0.0); generator.Emit(OpCodes.Br_S, endLabel); generator.MarkLabel(ifLabel); generator.Emit(OpCodes.Ldc_R8, 1.0); generator.MarkLabel(endLabel); } else if (operation.GetType() == typeof(LessOrEqualThan)) { LessOrEqualThan lessOrEqualThan = (LessOrEqualThan)operation; Label ifLabel = generator.DefineLabel(); Label endLabel = generator.DefineLabel(); GenerateMethodBody(generator, lessOrEqualThan.Argument1, functionRegistry); GenerateMethodBody(generator, lessOrEqualThan.Argument2, functionRegistry); generator.Emit(OpCodes.Ble_S, ifLabel); generator.Emit(OpCodes.Ldc_R8, 0.0); generator.Emit(OpCodes.Br_S, endLabel); generator.MarkLabel(ifLabel); generator.Emit(OpCodes.Ldc_R8, 1.0); generator.MarkLabel(endLabel); } else if (operation.GetType() == typeof(GreaterThan)) { GreaterThan greaterThan = (GreaterThan)operation; Label ifLabel = generator.DefineLabel(); Label endLabel = generator.DefineLabel(); GenerateMethodBody(generator, greaterThan.Argument1, functionRegistry); GenerateMethodBody(generator, greaterThan.Argument2, functionRegistry); generator.Emit(OpCodes.Bgt_S, ifLabel); generator.Emit(OpCodes.Ldc_R8, 0.0); generator.Emit(OpCodes.Br_S, endLabel); generator.MarkLabel(ifLabel); generator.Emit(OpCodes.Ldc_R8, 1.0); generator.MarkLabel(endLabel); } else if (operation.GetType() == typeof(GreaterOrEqualThan)) { GreaterOrEqualThan greaterOrEqualThan = (GreaterOrEqualThan)operation; Label ifLabel = generator.DefineLabel(); Label endLabel = generator.DefineLabel(); GenerateMethodBody(generator, greaterOrEqualThan.Argument1, functionRegistry); GenerateMethodBody(generator, greaterOrEqualThan.Argument2, functionRegistry); generator.Emit(OpCodes.Bge_S, ifLabel); generator.Emit(OpCodes.Ldc_R8, 0.0); generator.Emit(OpCodes.Br_S, endLabel); generator.MarkLabel(ifLabel); generator.Emit(OpCodes.Ldc_R8, 1.0); generator.MarkLabel(endLabel); } else if (operation.GetType() == typeof(Equal)) { Equal equal = (Equal)operation; Label ifLabel = generator.DefineLabel(); Label endLabel = generator.DefineLabel(); GenerateMethodBody(generator, equal.Argument1, functionRegistry); GenerateMethodBody(generator, equal.Argument2, functionRegistry); generator.Emit(OpCodes.Beq_S, ifLabel); generator.Emit(OpCodes.Ldc_R8, 0.0); generator.Emit(OpCodes.Br_S, endLabel); generator.MarkLabel(ifLabel); generator.Emit(OpCodes.Ldc_R8, 1.0); generator.MarkLabel(endLabel); } else if (operation.GetType() == typeof(NotEqual)) { NotEqual notEqual = (NotEqual)operation; Label ifLabel = generator.DefineLabel(); Label endLabel = generator.DefineLabel(); GenerateMethodBody(generator, notEqual.Argument1, functionRegistry); GenerateMethodBody(generator, notEqual.Argument2, functionRegistry); generator.Emit(OpCodes.Beq, ifLabel); generator.Emit(OpCodes.Ldc_R8, 1.0); generator.Emit(OpCodes.Br_S, endLabel); generator.MarkLabel(ifLabel); generator.Emit(OpCodes.Ldc_R8, 0.0); generator.MarkLabel(endLabel); } else if (operation.GetType() == typeof(Function)) { Function function = (Function)operation; FunctionInfo functionInfo = functionRegistry.GetFunctionInfo(function.FunctionName); Type funcType = GetFuncType(functionInfo.NumberOfParameters); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Callvirt, typeof(FormulaContext).GetProperty("FunctionRegistry").GetGetMethod()); generator.Emit(OpCodes.Ldstr, function.FunctionName); generator.Emit(OpCodes.Callvirt, typeof(IFunctionRegistry).GetMethod("GetFunctionInfo", new Type[] { typeof(string) })); generator.Emit(OpCodes.Callvirt, typeof(FunctionInfo).GetProperty("Function").GetGetMethod()); generator.Emit(OpCodes.Castclass, funcType); for (int i = 0; i < functionInfo.NumberOfParameters; i++) { GenerateMethodBody(generator, function.Arguments[i], functionRegistry); } generator.Emit(OpCodes.Call, funcType.GetMethod("Invoke")); } else { throw new ArgumentException(string.Format("Unsupported operation \"{0}\".", operation.GetType().FullName), "operation"); } }
private Expression GenerateMethodBody(Operation operation, ParameterExpression contextParameter, IFunctionRegistry functionRegistry) { if (operation == null) { throw new ArgumentNullException("operation"); } if (operation.GetType() == typeof(IntegerConstant)) { IntegerConstant constant = (IntegerConstant)operation; double value = constant.Value; return(Expression.Constant(value, typeof(double))); } else if (operation.GetType() == typeof(FloatingPointConstant)) { FloatingPointConstant constant = (FloatingPointConstant)operation; return(Expression.Constant(constant.Value, typeof(double))); } else if (operation.GetType() == typeof(Variable)) { Variable variable = (Variable)operation; Func <string, FormulaContext, double> getVariableValueOrThrow = PrecompiledMethods.GetVariableValueOrThrow; return(Expression.Call(null, getVariableValueOrThrow.GetMethodInfo(), Expression.Constant(variable.Name), contextParameter)); } else if (operation.GetType() == typeof(Multiplication)) { Multiplication multiplication = (Multiplication)operation; Expression argument1 = GenerateMethodBody(multiplication.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(multiplication.Argument2, contextParameter, functionRegistry); return(Expression.Multiply(argument1, argument2)); } else if (operation.GetType() == typeof(Addition)) { Addition addition = (Addition)operation; Expression argument1 = GenerateMethodBody(addition.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(addition.Argument2, contextParameter, functionRegistry); return(Expression.Add(argument1, argument2)); } else if (operation.GetType() == typeof(Subtraction)) { Subtraction addition = (Subtraction)operation; Expression argument1 = GenerateMethodBody(addition.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(addition.Argument2, contextParameter, functionRegistry); return(Expression.Subtract(argument1, argument2)); } else if (operation.GetType() == typeof(Division)) { Division division = (Division)operation; Expression dividend = GenerateMethodBody(division.Dividend, contextParameter, functionRegistry); Expression divisor = GenerateMethodBody(division.Divisor, contextParameter, functionRegistry); return(Expression.Divide(dividend, divisor)); } else if (operation.GetType() == typeof(Modulo)) { Modulo modulo = (Modulo)operation; Expression dividend = GenerateMethodBody(modulo.Dividend, contextParameter, functionRegistry); Expression divisor = GenerateMethodBody(modulo.Divisor, contextParameter, functionRegistry); return(Expression.Modulo(dividend, divisor)); } else if (operation.GetType() == typeof(Exponentiation)) { Exponentiation exponentation = (Exponentiation)operation; Expression @base = GenerateMethodBody(exponentation.Base, contextParameter, functionRegistry); Expression exponent = GenerateMethodBody(exponentation.Exponent, contextParameter, functionRegistry); return(Expression.Call(null, typeof(Math).GetRuntimeMethod("Pow", new Type[] { typeof(double), typeof(double) }), @base, exponent)); } else if (operation.GetType() == typeof(UnaryMinus)) { UnaryMinus unaryMinus = (UnaryMinus)operation; Expression argument = GenerateMethodBody(unaryMinus.Argument, contextParameter, functionRegistry); return(Expression.Negate(argument)); } else if (operation.GetType() == typeof(And)) { And and = (And)operation; Expression argument1 = Expression.NotEqual(GenerateMethodBody(and.Argument1, contextParameter, functionRegistry), Expression.Constant(0.0)); Expression argument2 = Expression.NotEqual(GenerateMethodBody(and.Argument2, contextParameter, functionRegistry), Expression.Constant(0.0)); return(Expression.Condition(Expression.And(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(Or)) { Or and = (Or)operation; Expression argument1 = Expression.NotEqual(GenerateMethodBody(and.Argument1, contextParameter, functionRegistry), Expression.Constant(0.0)); Expression argument2 = Expression.NotEqual(GenerateMethodBody(and.Argument2, contextParameter, functionRegistry), Expression.Constant(0.0)); return(Expression.Condition(Expression.Or(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(LessThan)) { LessThan lessThan = (LessThan)operation; Expression argument1 = GenerateMethodBody(lessThan.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(lessThan.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.LessThan(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(LessOrEqualThan)) { LessOrEqualThan lessOrEqualThan = (LessOrEqualThan)operation; Expression argument1 = GenerateMethodBody(lessOrEqualThan.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(lessOrEqualThan.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.LessThanOrEqual(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(GreaterThan)) { GreaterThan greaterThan = (GreaterThan)operation; Expression argument1 = GenerateMethodBody(greaterThan.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(greaterThan.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.GreaterThan(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(GreaterOrEqualThan)) { GreaterOrEqualThan greaterOrEqualThan = (GreaterOrEqualThan)operation; Expression argument1 = GenerateMethodBody(greaterOrEqualThan.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(greaterOrEqualThan.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.GreaterThanOrEqual(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(Equal)) { Equal equal = (Equal)operation; Expression argument1 = GenerateMethodBody(equal.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(equal.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.Equal(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(NotEqual)) { NotEqual notEqual = (NotEqual)operation; Expression argument1 = GenerateMethodBody(notEqual.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(notEqual.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.NotEqual(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(Function)) { Function function = (Function)operation; FunctionInfo functionInfo = functionRegistry.GetFunctionInfo(function.FunctionName); Type funcType; Type[] parameterTypes; Expression[] arguments; if (functionInfo.IsDynamicFunc) { funcType = typeof(DynamicFunc <double, double>); parameterTypes = new Type[] { typeof(double[]) }; Expression[] arrayArguments = new Expression[function.Arguments.Count]; for (int i = 0; i < function.Arguments.Count; i++) { arrayArguments[i] = GenerateMethodBody(function.Arguments[i], contextParameter, functionRegistry); } arguments = new Expression[1]; arguments[0] = NewArrayExpression.NewArrayInit(typeof(double), arrayArguments); } else { funcType = GetFuncType(functionInfo.NumberOfParameters); parameterTypes = (from i in Enumerable.Range(0, functionInfo.NumberOfParameters) select typeof(double)).ToArray(); arguments = new Expression[functionInfo.NumberOfParameters]; for (int i = 0; i < functionInfo.NumberOfParameters; i++) { arguments[i] = GenerateMethodBody(function.Arguments[i], contextParameter, functionRegistry); } } Expression getFunctionRegistry = Expression.Property(contextParameter, "FunctionRegistry"); ParameterExpression functionInfoVariable = Expression.Variable(typeof(FunctionInfo)); Expression funcInstance; if (!functionInfo.IsOverWritable) { funcInstance = Expression.Convert( Expression.Property( Expression.Call( getFunctionRegistry, typeof(IFunctionRegistry).GetRuntimeMethod("GetFunctionInfo", new Type[] { typeof(string) }), Expression.Constant(function.FunctionName)), "Function"), funcType); } else { funcInstance = Expression.Constant(functionInfo.Function, funcType); } return(Expression.Call( funcInstance, funcType.GetRuntimeMethod("Invoke", parameterTypes), arguments)); } else { throw new ArgumentException(string.Format("Unsupported operation \"{0}\".", operation.GetType().FullName), "operation"); } }
public double Execute(Operation operation, IFunctionRegistry functionRegistry, IConstantRegistry constantRegistry, IDictionary <string, double> variables) { if (operation == null) { throw new ArgumentNullException("operation"); } if (operation.GetType() == typeof(IntegerConstant)) { IntegerConstant constant = (IntegerConstant)operation; return(constant.Value); } else if (operation.GetType() == typeof(FloatingPointConstant)) { FloatingPointConstant constant = (FloatingPointConstant)operation; return(constant.Value); } else if (operation.GetType() == typeof(Variable)) { Variable variable = (Variable)operation; double value; bool variableFound = variables.TryGetValue(variable.Name, out value); if (variableFound) { return(value); } else { throw new VariableNotDefinedException(string.Format("The variable \"{0}\" used is not defined.", variable.Name)); } } else if (operation.GetType() == typeof(Multiplication)) { Multiplication multiplication = (Multiplication)operation; return(Execute(multiplication.Argument1, functionRegistry, constantRegistry, variables) * Execute(multiplication.Argument2, functionRegistry, constantRegistry, variables)); } else if (operation.GetType() == typeof(Addition)) { Addition addition = (Addition)operation; return(Execute(addition.Argument1, functionRegistry, constantRegistry, variables) + Execute(addition.Argument2, functionRegistry, constantRegistry, variables)); } else if (operation.GetType() == typeof(Subtraction)) { Subtraction addition = (Subtraction)operation; return(Execute(addition.Argument1, functionRegistry, constantRegistry, variables) - Execute(addition.Argument2, functionRegistry, constantRegistry, variables)); } else if (operation.GetType() == typeof(Division)) { Division division = (Division)operation; return(Execute(division.Dividend, functionRegistry, constantRegistry, variables) / Execute(division.Divisor, functionRegistry, constantRegistry, variables)); } else if (operation.GetType() == typeof(Modulo)) { Modulo division = (Modulo)operation; return(Execute(division.Dividend, functionRegistry, constantRegistry, variables) % Execute(division.Divisor, functionRegistry, constantRegistry, variables)); } else if (operation.GetType() == typeof(Exponentiation)) { Exponentiation exponentiation = (Exponentiation)operation; return(Math.Pow(Execute(exponentiation.Base, functionRegistry, constantRegistry, variables), Execute(exponentiation.Exponent, functionRegistry, constantRegistry, variables))); } else if (operation.GetType() == typeof(UnaryMinus)) { UnaryMinus unaryMinus = (UnaryMinus)operation; return(-Execute(unaryMinus.Argument, functionRegistry, constantRegistry, variables)); } else if (operation.GetType() == typeof(And)) { And and = (And)operation; var operation1 = Execute(and.Argument1, functionRegistry, constantRegistry, variables) != 0; var operation2 = Execute(and.Argument2, functionRegistry, constantRegistry, variables) != 0; return((operation1 && operation2) ? 1.0 : 0.0); } else if (operation.GetType() == typeof(Or)) { Or or = (Or)operation; var operation1 = Execute(or.Argument1, functionRegistry, constantRegistry, variables) != 0; var operation2 = Execute(or.Argument2, functionRegistry, constantRegistry, variables) != 0; return((operation1 || operation2) ? 1.0 : 0.0); } else if (operation.GetType() == typeof(LessThan)) { LessThan lessThan = (LessThan)operation; return((Execute(lessThan.Argument1, functionRegistry, constantRegistry, variables) < Execute(lessThan.Argument2, functionRegistry, constantRegistry, variables)) ? 1.0 : 0.0); } else if (operation.GetType() == typeof(LessOrEqualThan)) { LessOrEqualThan lessOrEqualThan = (LessOrEqualThan)operation; return((Execute(lessOrEqualThan.Argument1, functionRegistry, constantRegistry, variables) <= Execute(lessOrEqualThan.Argument2, functionRegistry, constantRegistry, variables)) ? 1.0 : 0.0); } else if (operation.GetType() == typeof(GreaterThan)) { GreaterThan greaterThan = (GreaterThan)operation; return((Execute(greaterThan.Argument1, functionRegistry, constantRegistry, variables) > Execute(greaterThan.Argument2, functionRegistry, constantRegistry, variables)) ? 1.0 : 0.0); } else if (operation.GetType() == typeof(GreaterOrEqualThan)) { GreaterOrEqualThan greaterOrEqualThan = (GreaterOrEqualThan)operation; return((Execute(greaterOrEqualThan.Argument1, functionRegistry, constantRegistry, variables) >= Execute(greaterOrEqualThan.Argument2, functionRegistry, constantRegistry, variables)) ? 1.0 : 0.0); } else if (operation.GetType() == typeof(Equal)) { Equal equal = (Equal)operation; return((Execute(equal.Argument1, functionRegistry, constantRegistry, variables) == Execute(equal.Argument2, functionRegistry, constantRegistry, variables)) ? 1.0 : 0.0); } else if (operation.GetType() == typeof(NotEqual)) { NotEqual notEqual = (NotEqual)operation; return((Execute(notEqual.Argument1, functionRegistry, constantRegistry, variables) != Execute(notEqual.Argument2, functionRegistry, constantRegistry, variables)) ? 1.0 : 0.0); } else if (operation.GetType() == typeof(Function)) { Function function = (Function)operation; FunctionInfo functionInfo = functionRegistry.GetFunctionInfo(function.FunctionName); double[] arguments = new double[functionInfo.IsDynamicFunc ? function.Arguments.Count : functionInfo.NumberOfParameters]; for (int i = 0; i < arguments.Length; i++) { arguments[i] = Execute(function.Arguments[i], functionRegistry, constantRegistry, variables); } return(Invoke(functionInfo.Function, arguments)); } else { throw new ArgumentException(string.Format("Unsupported operation \"{0}\".", operation.GetType().FullName), "operation"); } }
public ExecutionResult Execute(Operation operation, IFunctionRegistry functionRegistry, IDictionary <string, ExecutionResult> variables) { if (operation == null) { throw new ArgumentNullException("operation"); } if (operation.GetType() == typeof(UnitNumberConstant)) { UnitNumberConstant constant = (UnitNumberConstant)operation; return(new ExecutionResult(constant.Value)); } else if (operation.GetType() == typeof(FloatingPointConstant)) { FloatingPointConstant constant = (FloatingPointConstant)operation; return(new ExecutionResult(constant.Value)); } else if (operation.GetType() == typeof(Variable)) { Variable variable = (Variable)operation; ExecutionResult value; bool variableFound = variables.TryGetValue(variable.Name, out value); if (variableFound) { return(value); } else { throw new VariableNotDefinedException(string.Format("The variable \"{0}\" used is not defined.", variable.Name)); } } else if (operation.GetType() == typeof(Multiplication)) { Multiplication multiplication = (Multiplication)operation; var executionResult1 = Execute(multiplication.Argument1, functionRegistry, variables); var executionResult2 = Execute(multiplication.Argument2, functionRegistry, variables); return(ExecuteMultiplication(executionResult1, executionResult2)); } else if (operation.GetType() == typeof(Addition)) { Addition addition = (Addition)operation; var executionResult1 = Execute(addition.Argument1, functionRegistry, variables); var executionResult2 = Execute(addition.Argument2, functionRegistry, variables); return(ExecuteAddition(executionResult1, executionResult2));; } else if (operation.GetType() == typeof(Subtraction)) { Subtraction addition = (Subtraction)operation; var executionResult1 = Execute(addition.Argument1, functionRegistry, variables); var executionResult2 = Execute(addition.Argument2, functionRegistry, variables); return(ExecuteSubtraction(executionResult1, executionResult2)); } else if (operation.GetType() == typeof(Division)) { Division division = (Division)operation; var executionResult1 = Execute(division.Dividend, functionRegistry, variables); var executionResult2 = Execute(division.Divisor, functionRegistry, variables); return(ExecuteDivision(executionResult1, executionResult2)); } else if (operation.GetType() == typeof(Exponentiation)) { Exponentiation exponentiation = (Exponentiation)operation; var executionResult1 = Execute(exponentiation.Base, functionRegistry, variables); var executionResult2 = Execute(exponentiation.Exponent, functionRegistry, variables); return(ExecuteExponentiation(executionResult1, executionResult2)); } else if (operation.GetType() == typeof(ChangeUnit)) { ChangeUnit exponentiation = (ChangeUnit)operation; var executionResult1 = Execute(exponentiation.Argument1, functionRegistry, variables); return(ExecuteUnitChange(executionResult1, exponentiation.Unit)); } else if (operation.GetType() == typeof(UnaryMinus)) { UnaryMinus unaryMinus = (UnaryMinus)operation; var executionResult = Execute(unaryMinus.Argument, functionRegistry, variables); if (executionResult.DataType == DataType.Number) { return(new ExecutionResult(-(double)executionResult.Value)); } else { return(new ExecutionResult(-(UnitNumber)executionResult.Value)); } } else if (operation.GetType() == typeof(Function)) { Function function = (Function)operation; FunctionInfo functionInfo = functionRegistry.GetFunctionInfo(function.FunctionName); ExecutionResult[] arguments = new ExecutionResult[functionInfo.IsDynamicFunc ? function.Arguments.Count : functionInfo.NumberOfParameters]; for (int i = 0; i < arguments.Length; i++) { arguments[i] = Execute(function.Arguments[i], functionRegistry, variables); } return(Invoke(functionInfo.Function, arguments)); } else { throw new ArgumentException(string.Format("Unsupported operation \"{0}\".", operation.GetType().FullName), "operation"); } }
public double Execute(Operation operation, IFunctionRegistry functionRegistry, Dictionary <string, double> variables) { if (operation == null) { throw new ArgumentNullException("operation"); } if (operation.GetType() == typeof(IntegerConstant)) { IntegerConstant constant = (IntegerConstant)operation; return(constant.Value); } else if (operation.GetType() == typeof(FloatingPointConstant)) { FloatingPointConstant constant = (FloatingPointConstant)operation; return(constant.Value); } else if (operation.GetType() == typeof(Variable)) { Variable variable = (Variable)operation; if (variables.ContainsKey(variable.Name)) { return(variables[variable.Name]); } else { throw new VariableNotDefinedException(string.Format("The variable \"{0}\" used is not defined.", variable.Name)); } } else if (operation.GetType() == typeof(Multiplication)) { Multiplication multiplication = (Multiplication)operation; return(Execute(multiplication.Argument1, functionRegistry, variables) * Execute(multiplication.Argument2, functionRegistry, variables)); } else if (operation.GetType() == typeof(Addition)) { Addition addition = (Addition)operation; return(Execute(addition.Argument1, functionRegistry, variables) + Execute(addition.Argument2, functionRegistry, variables)); } else if (operation.GetType() == typeof(Subtraction)) { Subtraction addition = (Subtraction)operation; return(Execute(addition.Argument1, functionRegistry, variables) - Execute(addition.Argument2, functionRegistry, variables)); } else if (operation.GetType() == typeof(Division)) { Division division = (Division)operation; return(Execute(division.Dividend, functionRegistry, variables) / Execute(division.Divisor, functionRegistry, variables)); } else if (operation.GetType() == typeof(Modulo)) { Modulo division = (Modulo)operation; return(Execute(division.Dividend, functionRegistry, variables) % Execute(division.Divisor, functionRegistry, variables)); } else if (operation.GetType() == typeof(Exponentiation)) { Exponentiation exponentiation = (Exponentiation)operation; return(Math.Pow(Execute(exponentiation.Base, functionRegistry, variables), Execute(exponentiation.Exponent, functionRegistry, variables))); } else if (operation.GetType() == typeof(UnaryMinus)) { UnaryMinus unaryMinus = (UnaryMinus)operation; return(-Execute(unaryMinus.Argument, functionRegistry, variables)); } else if (operation.GetType() == typeof(Function)) { Function function = (Function)operation; FunctionInfo functionInfo = functionRegistry.GetFunctionInfo(function.FunctionName); double[] arguments = new double[functionInfo.NumberOfParameters]; for (int i = 0; i < arguments.Length; i++) { arguments[i] = Execute(function.Arguments[i], functionRegistry, variables); } return(Invoke(functionInfo.Function, arguments)); } else { throw new ArgumentException(string.Format("Unsupported operation \"{0}\".", operation.GetType().FullName), "operation"); } }
private Expression GenerateMethodBody(Operation operation, ParameterExpression contextParameter, IFunctionRegistry functionRegistry) { if (operation == null) { throw new ArgumentNullException("operation"); } if (operation.GetType() == typeof(IntegerConstant)) { IntegerConstant constant = (IntegerConstant)operation; return(Expression.Convert(Expression.Constant(constant.Value, typeof(int)), typeof(double))); } else if (operation.GetType() == typeof(FloatingPointConstant)) { FloatingPointConstant constant = (FloatingPointConstant)operation; return(Expression.Constant(constant.Value, typeof(double))); } else if (operation.GetType() == typeof(Variable)) { Type contextType = typeof(FormulaContext); Type dictionaryType = typeof(IDictionary <string, double>); Variable variable = (Variable)operation; Expression getVariables = Expression.Property(contextParameter, "Variables"); ParameterExpression value = Expression.Variable(typeof(double), "value"); Expression variableFound = Expression.Call(getVariables, dictionaryType.GetRuntimeMethod("TryGetValue", new Type[] { typeof(string), typeof(double).MakeByRefType() }), Expression.Constant(variable.Name), value); Expression throwException = Expression.Throw( Expression.New(typeof(VariableNotDefinedException).GetConstructor(new Type[] { typeof(string) }), Expression.Constant(string.Format("The variable \"{0}\" used is not defined.", variable.Name)))); LabelTarget returnLabel = Expression.Label(typeof(double)); return(Expression.Block( new[] { value }, Expression.IfThenElse( variableFound, Expression.Return(returnLabel, value), throwException ), Expression.Label(returnLabel, Expression.Constant(0.0)) )); } else if (operation.GetType() == typeof(Multiplication)) { Multiplication multiplication = (Multiplication)operation; Expression argument1 = GenerateMethodBody(multiplication.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(multiplication.Argument2, contextParameter, functionRegistry); return(Expression.Multiply(argument1, argument2)); } else if (operation.GetType() == typeof(Addition)) { Addition addition = (Addition)operation; Expression argument1 = GenerateMethodBody(addition.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(addition.Argument2, contextParameter, functionRegistry); return(Expression.Add(argument1, argument2)); } else if (operation.GetType() == typeof(Subtraction)) { Subtraction addition = (Subtraction)operation; Expression argument1 = GenerateMethodBody(addition.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(addition.Argument2, contextParameter, functionRegistry); return(Expression.Subtract(argument1, argument2)); } else if (operation.GetType() == typeof(Division)) { Division division = (Division)operation; Expression dividend = GenerateMethodBody(division.Dividend, contextParameter, functionRegistry); Expression divisor = GenerateMethodBody(division.Divisor, contextParameter, functionRegistry); return(Expression.Divide(dividend, divisor)); } else if (operation.GetType() == typeof(Modulo)) { Modulo modulo = (Modulo)operation; Expression dividend = GenerateMethodBody(modulo.Dividend, contextParameter, functionRegistry); Expression divisor = GenerateMethodBody(modulo.Divisor, contextParameter, functionRegistry); return(Expression.Modulo(dividend, divisor)); } else if (operation.GetType() == typeof(Exponentiation)) { Exponentiation exponentation = (Exponentiation)operation; Expression @base = GenerateMethodBody(exponentation.Base, contextParameter, functionRegistry); Expression exponent = GenerateMethodBody(exponentation.Exponent, contextParameter, functionRegistry); return(Expression.Call(null, typeof(Math).GetRuntimeMethod("Pow", new Type[] { typeof(double), typeof(double) }), @base, exponent)); } else if (operation.GetType() == typeof(UnaryMinus)) { UnaryMinus unaryMinus = (UnaryMinus)operation; Expression argument = GenerateMethodBody(unaryMinus.Argument, contextParameter, functionRegistry); return(Expression.Negate(argument)); } else if (operation.GetType() == typeof(And)) { And and = (And)operation; Expression argument1 = Expression.NotEqual(GenerateMethodBody(and.Argument1, contextParameter, functionRegistry), Expression.Constant(0.0)); Expression argument2 = Expression.NotEqual(GenerateMethodBody(and.Argument2, contextParameter, functionRegistry), Expression.Constant(0.0)); return(Expression.Condition(Expression.And(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(Or)) { Or and = (Or)operation; Expression argument1 = Expression.NotEqual(GenerateMethodBody(and.Argument1, contextParameter, functionRegistry), Expression.Constant(0.0)); Expression argument2 = Expression.NotEqual(GenerateMethodBody(and.Argument2, contextParameter, functionRegistry), Expression.Constant(0.0)); return(Expression.Condition(Expression.Or(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(LessThan)) { LessThan lessThan = (LessThan)operation; Expression argument1 = GenerateMethodBody(lessThan.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(lessThan.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.LessThan(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(LessOrEqualThan)) { LessOrEqualThan lessOrEqualThan = (LessOrEqualThan)operation; Expression argument1 = GenerateMethodBody(lessOrEqualThan.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(lessOrEqualThan.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.LessThanOrEqual(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(GreaterThan)) { GreaterThan greaterThan = (GreaterThan)operation; Expression argument1 = GenerateMethodBody(greaterThan.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(greaterThan.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.GreaterThan(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(GreaterOrEqualThan)) { GreaterOrEqualThan greaterOrEqualThan = (GreaterOrEqualThan)operation; Expression argument1 = GenerateMethodBody(greaterOrEqualThan.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(greaterOrEqualThan.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.GreaterThanOrEqual(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(Equal)) { Equal equal = (Equal)operation; Expression argument1 = GenerateMethodBody(equal.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(equal.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.Equal(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(NotEqual)) { NotEqual notEqual = (NotEqual)operation; Expression argument1 = GenerateMethodBody(notEqual.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(notEqual.Argument2, contextParameter, functionRegistry); return(Expression.Condition(Expression.NotEqual(argument1, argument2), Expression.Constant(1.0), Expression.Constant(0.0))); } else if (operation.GetType() == typeof(Function)) { Function function = (Function)operation; FunctionInfo functionInfo = functionRegistry.GetFunctionInfo(function.FunctionName); Type funcType; Type[] parameterTypes; Expression[] arguments; if (functionInfo.IsDynamicFunc) { funcType = typeof(DynamicFunc <double, double>); parameterTypes = new Type[] { typeof(double[]) }; Expression[] arrayArguments = new Expression[function.Arguments.Count]; for (int i = 0; i < function.Arguments.Count; i++) { arrayArguments[i] = GenerateMethodBody(function.Arguments[i], contextParameter, functionRegistry); } arguments = new Expression[1]; arguments[0] = NewArrayExpression.NewArrayInit(typeof(double), arrayArguments); } else { funcType = GetFuncType(functionInfo.NumberOfParameters); parameterTypes = (from i in Enumerable.Range(0, functionInfo.NumberOfParameters) select typeof(double)).ToArray(); arguments = new Expression[functionInfo.NumberOfParameters]; for (int i = 0; i < functionInfo.NumberOfParameters; i++) { arguments[i] = GenerateMethodBody(function.Arguments[i], contextParameter, functionRegistry); } } Expression getFunctionRegistry = Expression.Property(contextParameter, "FunctionRegistry"); ParameterExpression functionInfoVariable = Expression.Variable(typeof(FunctionInfo)); return(Expression.Block( new[] { functionInfoVariable }, Expression.Assign( functionInfoVariable, Expression.Call(getFunctionRegistry, typeof(IFunctionRegistry).GetRuntimeMethod("GetFunctionInfo", new Type[] { typeof(string) }), Expression.Constant(function.FunctionName)) ), Expression.Call( Expression.Convert(Expression.Property(functionInfoVariable, "Function"), funcType), funcType.GetRuntimeMethod("Invoke", parameterTypes), arguments))); } else { throw new ArgumentException(string.Format("Unsupported operation \"{0}\".", operation.GetType().FullName), "operation"); } }
private void GenerateMethodBody(ILGenerator generator, Operation operation) { if (operation == null) { throw new ArgumentNullException("operation"); } if (operation.GetType() == typeof(IntegerConstant)) { IntegerConstant constant = (IntegerConstant)operation; generator.Emit(OpCodes.Ldc_I4, constant.Value); generator.Emit(OpCodes.Conv_R8); } else if (operation.GetType() == typeof(FloatingPointConstant)) { FloatingPointConstant constant = (FloatingPointConstant)operation; generator.Emit(OpCodes.Ldc_R8, constant.Value); } else if (operation.GetType() == typeof(Variable)) { Type dictionaryType = typeof(Dictionary <string, double>); Variable variable = (Variable)operation; Label throwExceptionLabel = generator.DefineLabel(); Label returnLabel = generator.DefineLabel(); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldstr, variable.Name); generator.Emit(OpCodes.Callvirt, dictionaryType.GetMethod("ContainsKey", new Type[] { typeof(string) })); generator.Emit(OpCodes.Ldc_I4_0); generator.Emit(OpCodes.Ceq); generator.Emit(OpCodes.Brtrue_S, throwExceptionLabel); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldstr, variable.Name); generator.Emit(OpCodes.Callvirt, dictionaryType.GetMethod("get_Item", new Type[] { typeof(string) })); generator.Emit(OpCodes.Br_S, returnLabel); generator.MarkLabel(throwExceptionLabel); generator.Emit(OpCodes.Ldstr, string.Format("The variable \"{0}\" used is not defined.", variable.Name)); generator.Emit(OpCodes.Newobj, typeof(VariableNotDefinedException).GetConstructor(new Type[] { typeof(string) })); generator.Emit(OpCodes.Throw); generator.MarkLabel(returnLabel); } else if (operation.GetType() == typeof(Multiplication)) { Multiplication multiplication = (Multiplication)operation; GenerateMethodBody(generator, multiplication.Argument1); GenerateMethodBody(generator, multiplication.Argument2); generator.Emit(OpCodes.Mul); } else if (operation.GetType() == typeof(Addition)) { Addition addition = (Addition)operation; GenerateMethodBody(generator, addition.Argument1); GenerateMethodBody(generator, addition.Argument2); generator.Emit(OpCodes.Add); } else if (operation.GetType() == typeof(Substraction)) { Substraction addition = (Substraction)operation; GenerateMethodBody(generator, addition.Argument1); GenerateMethodBody(generator, addition.Argument2); generator.Emit(OpCodes.Sub); } else if (operation.GetType() == typeof(Division)) { Division division = (Division)operation; GenerateMethodBody(generator, division.Dividend); GenerateMethodBody(generator, division.Divisor); generator.Emit(OpCodes.Div); } else if (operation.GetType() == typeof(Exponentiation)) { Exponentiation exponentation = (Exponentiation)operation; GenerateMethodBody(generator, exponentation.Base); GenerateMethodBody(generator, exponentation.Exponent); generator.Emit(OpCodes.Call, typeof(Math).GetMethod("Pow")); } else if (operation.GetType() == typeof(Function)) { Function function = (Function)operation; switch (function.FunctionType) { case FunctionType.Sine: GenerateMethodBody(generator, function.Arguments[0]); generator.Emit(OpCodes.Call, typeof(Math).GetMethod("Sin")); break; case FunctionType.Cosine: GenerateMethodBody(generator, function.Arguments[0]); generator.Emit(OpCodes.Call, typeof(Math).GetMethod("Cos")); break; case FunctionType.Loge: GenerateMethodBody(generator, function.Arguments[0]); generator.Emit(OpCodes.Call, typeof(Math).GetMethod("Log", new Type[] { typeof(double) })); break; case FunctionType.Log10: GenerateMethodBody(generator, function.Arguments[0]); generator.Emit(OpCodes.Call, typeof(Math).GetMethod("Log10")); break; case FunctionType.Logn: GenerateMethodBody(generator, function.Arguments[0]); GenerateMethodBody(generator, function.Arguments[1]); generator.Emit(OpCodes.Call, typeof(Math).GetMethod("Log", new Type[] { typeof(double), typeof(double) })); break; default: throw new ArgumentException(string.Format("Unsupported function \"{0}\".", function.FunctionType), "operation"); } } else { throw new ArgumentException(string.Format("Unsupported operation \"{0}\".", operation.GetType().FullName), "operation"); } }
private Expression GenerateMethodBody(Operation operation, ParameterExpression contextParameter, IFunctionRegistry functionRegistry) { if (operation == null) { throw new ArgumentNullException("operation"); } if (operation.GetType() == typeof(UnitNumberConstant)) { var constant = (UnitNumberConstant)operation; var ret = new ExecutionResult(constant.Value); return(Expression.Constant(ret, typeof(ExecutionResult))); } else if (operation.GetType() == typeof(FloatingPointConstant)) { FloatingPointConstant constant = (FloatingPointConstant)operation; var ret = new ExecutionResult(constant.Value); return(Expression.Constant(ret, typeof(ExecutionResult))); } else if (operation.GetType() == typeof(Variable)) { Type contextType = typeof(FormulaContext); Type dictionaryType = typeof(IDictionary <string, ExecutionResult>); Variable variable = (Variable)operation; Expression getVariables = Expression.Property(contextParameter, "Variables"); ParameterExpression value = Expression.Variable(typeof(ExecutionResult), "value"); Expression variableFound = Expression.Call(getVariables, dictionaryType.GetMethod("TryGetValue", new Type[] { typeof(string), typeof(ExecutionResult).MakeByRefType() }), Expression.Constant(variable.Name), value); Expression throwException = Expression.Throw( Expression.New(typeof(VariableNotDefinedException).GetConstructor(new Type[] { typeof(string) }), Expression.Constant(string.Format("The variable \"{0}\" used is not defined.", variable.Name)))); LabelTarget returnLabel = Expression.Label(typeof(ExecutionResult)); return(Expression.Block( new[] { value }, Expression.IfThenElse( variableFound, Expression.Return(returnLabel, value), throwException ), Expression.Label(returnLabel, Expression.Constant(new ExecutionResult(0))) )); } else if (operation.GetType() == typeof(Multiplication)) { Multiplication multiplication = (Multiplication)operation; Expression argument1 = GenerateMethodBody(multiplication.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(multiplication.Argument2, contextParameter, functionRegistry); return(Expression.Multiply(argument1, argument2)); } else if (operation.GetType() == typeof(Addition)) { Addition addition = (Addition)operation; Expression argument1 = GenerateMethodBody(addition.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(addition.Argument2, contextParameter, functionRegistry); return(Expression.Add(argument1, argument2)); } else if (operation.GetType() == typeof(Subtraction)) { Subtraction addition = (Subtraction)operation; Expression argument1 = GenerateMethodBody(addition.Argument1, contextParameter, functionRegistry); Expression argument2 = GenerateMethodBody(addition.Argument2, contextParameter, functionRegistry); return(Expression.Subtract(argument1, argument2)); } else if (operation.GetType() == typeof(Division)) { Division division = (Division)operation; Expression dividend = GenerateMethodBody(division.Dividend, contextParameter, functionRegistry); Expression divisor = GenerateMethodBody(division.Divisor, contextParameter, functionRegistry); return(Expression.Divide(dividend, divisor)); } else if (operation.GetType() == typeof(Exponentiation)) { Exponentiation exponentation = (Exponentiation)operation; Expression @base = GenerateMethodBody(exponentation.Base, contextParameter, functionRegistry); Expression exponent = GenerateMethodBody(exponentation.Exponent, contextParameter, functionRegistry); return(Expression.Call(@base, typeof(ExecutionResult).GetMethod("Pow", new Type[] { typeof(ExecutionResult) }), exponent)); } else if (operation.GetType() == typeof(UnaryMinus)) { UnaryMinus unaryMinus = (UnaryMinus)operation; Expression argument = GenerateMethodBody(unaryMinus.Argument, contextParameter, functionRegistry); return(Expression.Negate(argument)); } else if (operation.GetType() == typeof(Function)) { Function function = (Function)operation; FunctionInfo functionInfo = functionRegistry.GetFunctionInfo(function.FunctionName); Type funcType; Type[] parameterTypes; Expression[] arguments; if (functionInfo.IsDynamicFunc) { funcType = typeof(DynamicFunc <ExecutionResult, ExecutionResult>); parameterTypes = new Type[] { typeof(ExecutionResult[]) }; Expression[] arrayArguments = new Expression[function.Arguments.Count]; for (int i = 0; i < function.Arguments.Count; i++) { arrayArguments[i] = GenerateMethodBody(function.Arguments[i], contextParameter, functionRegistry); } arguments = new Expression[1]; arguments[0] = Expression.NewArrayInit(typeof(ExecutionResult), arrayArguments); } else { funcType = GetFuncType(functionInfo.NumberOfParameters); parameterTypes = (from i in Enumerable.Range(0, functionInfo.NumberOfParameters) select typeof(ExecutionResult)).ToArray(); arguments = new Expression[functionInfo.NumberOfParameters]; for (int i = 0; i < functionInfo.NumberOfParameters; i++) { arguments[i] = GenerateMethodBody(function.Arguments[i], contextParameter, functionRegistry); } } Expression getFunctionRegistry = Expression.Property(contextParameter, "FunctionRegistry"); ParameterExpression functionInfoVariable = Expression.Variable(typeof(FunctionInfo)); return(Expression.Block( new[] { functionInfoVariable }, Expression.Assign( functionInfoVariable, Expression.Call(getFunctionRegistry, typeof(IFunctionRegistry).GetMethod("GetFunctionInfo", new Type[] { typeof(string) }), Expression.Constant(function.FunctionName)) ), Expression.Call( Expression.Convert(Expression.Property(functionInfoVariable, "Function"), funcType), funcType.GetMethod("Invoke", parameterTypes), arguments))); } else if (operation.GetType() == typeof(ChangeUnit)) { ChangeUnit oper = (ChangeUnit)operation; Expression argument = GenerateMethodBody(oper.Argument1, contextParameter, functionRegistry); return(Expression.Call(argument, typeof(ExecutionResult).GetMethod("ChangeUnit", new Type[] { typeof(Unit) }), Expression.Constant(oper.Unit, typeof(Unit)))); } else { throw new ArgumentException( string.Format("Unsupported operation \"{0}\".", operation.GetType().FullName), "operation"); } }
public double Execute(Operation operation, Dictionary <string, double> variables) { if (operation == null) { throw new ArgumentNullException("operation"); } if (operation.GetType() == typeof(IntegerConstant)) { IntegerConstant constant = (IntegerConstant)operation; return(constant.Value); } else if (operation.GetType() == typeof(FloatingPointConstant)) { FloatingPointConstant constant = (FloatingPointConstant)operation; return(constant.Value); } else if (operation.GetType() == typeof(Variable)) { Variable variable = (Variable)operation; if (variables.ContainsKey(variable.Name)) { return(variables[variable.Name]); } else { throw new VariableNotDefinedException(string.Format("The variable \"{0}\" used is not defined.", variable.Name)); } } else if (operation.GetType() == typeof(Multiplication)) { Multiplication multiplication = (Multiplication)operation; return(Execute(multiplication.Argument1, variables) * Execute(multiplication.Argument2, variables)); } else if (operation.GetType() == typeof(Addition)) { Addition addition = (Addition)operation; return(Execute(addition.Argument1, variables) + Execute(addition.Argument2, variables)); } else if (operation.GetType() == typeof(Substraction)) { Substraction addition = (Substraction)operation; return(Execute(addition.Argument1, variables) - Execute(addition.Argument2, variables)); } else if (operation.GetType() == typeof(Division)) { Division division = (Division)operation; return(Execute(division.Dividend, variables) / Execute(division.Divisor, variables)); } else if (operation.GetType() == typeof(Exponentiation)) { Exponentiation exponentiation = (Exponentiation)operation; return(Math.Pow(Execute(exponentiation.Base, variables), Execute(exponentiation.Exponent, variables))); } else if (operation.GetType() == typeof(Function)) { Function function = (Function)operation; switch (function.FunctionType) { case FunctionType.Sine: return(Math.Sin(Execute(function.Arguments[0], variables))); case FunctionType.Cosine: return(Math.Cos(Execute(function.Arguments[0], variables))); case FunctionType.Loge: return(Math.Log(Execute(function.Arguments[0], variables))); case FunctionType.Log10: return(Math.Log10(Execute(function.Arguments[0], variables))); case FunctionType.Logn: return(Math.Log(Execute(function.Arguments[0], variables), Execute(function.Arguments[1], variables))); default: throw new ArgumentException(string.Format("Unsupported function \"{0}\".", function.FunctionType), "operation"); } } else { throw new ArgumentException(string.Format("Unsupported operation \"{0}\".", operation.GetType().FullName), "operation"); } }