private static CompiledExpression CompilePostfix(TokenCollection tokens, string originalInfix, bool optimizeGraphingArg) { // The following is used for outputting to a physical assembly and testing with peverify.exe /* AssemblyName an = new AssemblyName("ExpressionOutput"); AppDomain ad = AppDomain.CurrentDomain; AssemblyBuilder ab = ad.DefineDynamicAssembly(an, AssemblyBuilderAccess.Save); ModuleBuilder mb = ab.DefineDynamicModule(an.Name, "ExpressionOutput.dll"); TypeBuilder tb = mb.DefineType("ExpressionOutput", TypeAttributes.Public | TypeAttributes.Class); MethodBuilder meth = tb.DefineMethod("ExpressionOutput", MethodAttributes.Public | MethodAttributes.Static, typeof(double), new[] { typeof(double[]), typeof(Calculator) }); */ // Signature: double Expression(double[] args, Calculator calc) var expression = new DynamicMethod("Expression", typeof(double), new[] { typeof(double[]), typeof(Calculator) }, typeof(Calculator)); ILGenerator il = expression.GetILGenerator(); var state = new CompilerState(optimizeGraphingArg); OptimizeWholePowers(tokens); bool isConstant = true; if (tokens.Count == 0) { il.Emit(OpCodes.Ldc_R8, 0D); } else { foreach (Token t in tokens) { if (!(t is OperatorToken || t is ValueToken || t is NegateToken)) { // If the token is anything other than an operator or value, it is not a constant isConstant = false; } t.EmitIl(il, state); } if (state.StackHeight != 1) { throw new FormatException("A disproportionate number of operators and values are present."); } } // Return the value il.Emit(OpCodes.Ret); /* tb.CreateType(); ab.Save("ExpressionOutput.dll"); */ return new CompiledExpression(expression, state, originalInfix, isConstant); }
/// <summary> /// Initializes a new instance of the CompiledExpression class. /// </summary> /// <param name="dynamicMethod">The dynamic method containing the emitted IL bytecode.</param> /// <param name="args">The list of arguments used by <paramref name="dynamicMethod"/>. This list should /// not contain duplicates: only one instance of each unique identifier should be included.</param> /// <param name="originalExpression">The original expression that this compiled version represents.</param> internal CompiledExpression(DynamicMethod dynamicMethod, CompilerState state, string originalExpression, bool isConstant) { Method = dynamicMethod; OriginalExpression = originalExpression; IsConstant = isConstant; // Sort the argument list by its local index state.Arguments.Sort((a1, a2) => a1.Index.CompareTo(a2.Index)); // Make a copy of the list to prevent outside modification Argument[] argsCopy = new Argument[state.Arguments.Count]; state.Arguments.CopyTo(argsCopy); Arguments = new ReadOnlyCollection<Argument>(argsCopy); ArgumentCount = Arguments.Count; GraphingArgumentPresent = state.GraphingArgumentLocal != null; _compiled = (Func<double[], Calculator, double>)dynamicMethod.CreateDelegate(typeof(Func<double[], Calculator, double>)); }