112 lines
5.1 KiB
C#
112 lines
5.1 KiB
C#
/*****************************************************************************
|
|
|
|
This class has been written by Łukasz Światkowski
|
|
Cleaned up spaghetti code and improved by Elmü (elmue@gmx.de)
|
|
|
|
*****************************************************************************/
|
|
|
|
using Microsoft.CSharp;
|
|
using System;
|
|
using System.CodeDom.Compiler;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using delRendererFunction = Plot3D.Editor3D.delRendererFunction;
|
|
|
|
namespace Plot3D
|
|
{
|
|
public delegate double delCompiledFunction(params double[] x);
|
|
|
|
public static class FunctionCompiler
|
|
{
|
|
private const String EVAL_CLASS =
|
|
"using {1};\n"
|
|
+ "public class Eval\n"
|
|
+ "{{\n"
|
|
+ " public static double e {{ get {{ return System.Math.E; }} }}\n"
|
|
+ " public static double pi {{ get {{ return System.Math.PI; }} }}\n"
|
|
// -------------------------------------------------------
|
|
+ " public static double abs (double x) {{ return System.Math.Abs(x); }}\n"
|
|
+ " public static double acos (double x) {{ return System.Math.Acos(x); }}\n"
|
|
+ " public static double asin (double x) {{ return System.Math.Asin(x); }}\n"
|
|
+ " public static double atan (double x) {{ return System.Math.Atan(x); }}\n"
|
|
+ " public static double atan2(double x, double y) {{ return System.Math.Atan2(x, y); }}\n"
|
|
+ " public static double ceil (double x) {{ return System.Math.Ceiling(x); }}\n"
|
|
+ " public static double cos (double x) {{ return System.Math.Cos(x); }}\n"
|
|
+ " public static double cosh (double x) {{ return System.Math.Cosh(x); }}\n"
|
|
+ " public static double exp (double x) {{ return System.Math.Exp(x); }}\n"
|
|
+ " public static double floor(double x) {{ return System.Math.Floor(x); }}\n"
|
|
+ " public static double log (double x) {{ return System.Math.Log(x); }}\n"
|
|
+ " public static double log2 (double x) {{ return System.Math.Log(x, 2.0); }}\n"
|
|
+ " public static double log10(double x) {{ return System.Math.Log10(x); }}\n"
|
|
+ " public static double max (double x, double y) {{ return System.Math.Max(x, y); }}\n"
|
|
+ " public static double min (double x, double y) {{ return System.Math.Min(x, y); }}\n"
|
|
+ " public static double pow (double x, double y) {{ return System.Math.Pow(x, y); }}\n"
|
|
+ " public static double round(double x) {{ return System.Math.Round(x); }}\n"
|
|
+ " public static double sign (double x) {{ return System.Math.Sign(x); }}\n"
|
|
+ " public static double sin (double x) {{ return System.Math.Sin(x); }}\n"
|
|
+ " public static double sinh (double x) {{ return System.Math.Sinh(x); }}\n"
|
|
+ " public static double sqrt (double x) {{ return System.Math.Sqrt(x); }}\n"
|
|
+ " public static double tan (double x) {{ return System.Math.Tan(x); }}\n"
|
|
+ " public static double tanh (double x) {{ return System.Math.Tanh(x); }}\n"
|
|
// -------------------------------------------------------
|
|
+ " public static double __eval(params double[] __X)\n"
|
|
+ " {{\n"
|
|
+ " double x = __X[0];\n"
|
|
+ " double y = __X[1];\n"
|
|
+ " return {0};\n"
|
|
+ " }}\n"
|
|
+ " public static {2} __get()\n"
|
|
+ " {{\n"
|
|
+ " return __eval;\n"
|
|
+ " }}\n"
|
|
+ "}}";
|
|
|
|
public static delRendererFunction Compile(string functionBody)
|
|
{
|
|
functionBody = functionBody.Trim().ToLower();
|
|
if (functionBody.Contains(";"))
|
|
throw new Exception("Function string cannot contain semicolon");
|
|
|
|
string s_Class = string.Format(EVAL_CLASS, functionBody, typeof(delCompiledFunction).Namespace, typeof(delCompiledFunction).Name);
|
|
|
|
CSharpCodeProvider i_Provider = new CSharpCodeProvider();
|
|
CompilerParameters i_Params = new CompilerParameters();
|
|
i_Params.CompilerOptions = "/t:library";
|
|
i_Params.GenerateInMemory = true;
|
|
i_Params.ReferencedAssemblies.Add("mscorlib.dll");
|
|
i_Params.ReferencedAssemblies.Add("System.dll");
|
|
i_Params.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);
|
|
|
|
CompilerResults i_Result = i_Provider.CompileAssemblyFromSource(i_Params, s_Class);
|
|
if (i_Result.Errors.HasErrors)
|
|
{
|
|
StringBuilder s_Error = new StringBuilder();
|
|
if (i_Result.Errors.Count == 1)
|
|
s_Error.Append("Compilation error:\n");
|
|
else
|
|
s_Error.AppendFormat("{0} Compilation errors:\n", i_Result.Errors.Count);
|
|
|
|
foreach (CompilerError i_Error in i_Result.Errors)
|
|
{
|
|
s_Error.Append(i_Error.ErrorText);
|
|
s_Error.Append("\n");
|
|
}
|
|
|
|
s_Error.Append("\nSupported math functions are:\n"
|
|
+ "e, pi, abs(), acos(), asin(), atan(), atan2(), ceil(), cos(), cosh(), "
|
|
+ "exp(), floor(), log(), log2(), log10(), max(), min(), pow(), "
|
|
+ "round(), sign(), sin(), sinh(), sqrt(), tan(), tanh()\n");
|
|
|
|
throw new Exception(s_Error.ToString());
|
|
}
|
|
|
|
MethodInfo i_Method = i_Result.CompiledAssembly.GetType("Eval").GetMethod("__get");
|
|
delCompiledFunction f_Compiled = (delCompiledFunction)i_Method.Invoke(null, null);
|
|
delRendererFunction f_Render = delegate (double X, double Y)
|
|
{
|
|
return f_Compiled(X, Y);
|
|
};
|
|
return f_Render;
|
|
}
|
|
}
|
|
} |