Skip to content
Snippets Groups Projects
Commit 0e30a644 authored by MaZiFAU's avatar MaZiFAU
Browse files

OMDoc to C# dynamic function builder 1.0

parent cfdc0ba3
No related branches found
No related tags found
No related merge requests found
......@@ -59,11 +59,14 @@ public static class MMTURIs
public static class MMTtoLambdaExpression<T>
{
private static LambdaExpression @default = Expression.Lambda(Expression.Default(typeof(T)), null);
public static readonly LambdaExpression @default = Expression.Lambda(Expression.Default(typeof(T)), null);
private static uint param_counter = 0; //for better debugs
// TODO: Populate Dictionaries
#region ExpressionDictionaries
private static Dictionary<string, Func<LambdaExpression>> MMTtoLambdaMaker = new()
private static readonly Dictionary<string, Func<LambdaExpression[], LambdaExpression>> MMTtoLambdaMaker = new()
{
{ "sin",
MakeSin},
......@@ -71,7 +74,7 @@ public static class MMTtoLambdaExpression<T>
MakeCos},
};
private static Dictionary<string, ExpressionType> MMTtoBinaryExpressionType = new()
private static readonly Dictionary<string, ExpressionType> MMTtoBinaryExpressionType = new()
{
{ "Add",
ExpressionType.Add},
......@@ -149,10 +152,14 @@ public static class MMTtoLambdaExpression<T>
ExpressionType.SubtractChecked},
};
private static Dictionary<string, ExpressionType> MMTtoUnaryExpressionType = new()
private static readonly Dictionary<string, ExpressionType> MMTtoUnaryExpressionType = new()
{
//{ "Constant", // Not Unary
// ExpressionType.Constant},
{ "Convert",
ExpressionType.Convert},
{ "ConvertChecked",
ExpressionType.ConvertChecked},
{ "Decrement",
ExpressionType.Decrement},
{ "Increment",
......@@ -179,71 +186,97 @@ public static class MMTtoLambdaExpression<T>
#endregion ExpressionDictionaries
public static LambdaExpression MakeLambdaExpression(string URI)
public static LambdaExpression MakeLambdaExpression(string URI, LambdaExpression[] args_lamda = null)
{
void ThrowArgumentException(ExpressionType expression_cast, int expected)
{
throw new ArgumentException(string.Format(
"\"Wrong number of Arguments. Required: {2}. Supplied: {3}.\\n\\tFor URI:\\\"{0}\\\"\\n\\tmapped to:\\\"{1}\\\"\"",
URI, expression_cast, expected, args_lamda.Count()
));
}
ParameterExpression[] args_param = args_lamda?.SelectMany(l => l.Parameters).ToArray();
if (MMTtoUnaryExpressionType.TryGetValue(URI, out var unnary_type))
{
ParameterExpression[] args = new ParameterExpression[] {
Expression.Parameter(typeof(T))
};
return Expression.Lambda(Expression.MakeUnary(unnary_type, args[0], typeof(T)), args);
if (args_lamda == null) {
ParameterExpression[] args = new ParameterExpression[] {
Expression.Parameter(typeof(T), "PNamed_" + (++param_counter).ToString()),
};
return Expression.Lambda(Expression.MakeUnary(unnary_type, args[0], typeof(T)), args);
}
else {
if (args_lamda.Count() < 1)
ThrowArgumentException(unnary_type, 1);
Type UnarySecondArgument = args_lamda.Count() < 2 ? null : args_lamda[1].ReturnType;
return Expression.Lambda(Expression.MakeUnary(unnary_type, args_lamda[0].Body, UnarySecondArgument), args_param);
}
}
else if (MMTtoBinaryExpressionType.TryGetValue(URI, out var binary_type))
{
ParameterExpression[] args = new ParameterExpression[] {
Expression.Parameter(typeof(T)),
Expression.Parameter(typeof(T))
};
return Expression.Lambda(Expression.MakeBinary(binary_type, args[0], args[1]), args);
if (args_lamda == null) {
ParameterExpression[] args = new ParameterExpression[] {
Expression.Parameter(typeof(T), "PNamed_" + (++param_counter).ToString()),
Expression.Parameter(typeof(T), "PNamed_" + (++param_counter).ToString()),
};
return Expression.Lambda(Expression.MakeBinary(binary_type, args[0], args[1]), args);
}
else {
if (args_lamda.Count() != 2)
ThrowArgumentException(binary_type, 2);
return Expression.Lambda(Expression.MakeBinary(binary_type, args_lamda[0].Body, args_lamda[1].Body), args_param);
}
}
else if (MMTtoLambdaMaker.TryGetValue(URI, out var lamda_maker))
{
return lamda_maker();
return lamda_maker(args_lamda ?? null); //args_lamda == null ok
}
throw new NotImplementedException("Could not map URI: \"" + URI + "\"");
}
private static Expression<Func<T, T>> ParseFuncTUUT<U>(Func<U,U> func)
=> (T x) =>
(T) Convert.ChangeType(
func(
(U) Convert.ChangeType(
x,
typeof(U)
)
),
typeof(T)
);
private static LambdaExpression ExpresionFuncToLambda(Expression func, uint nTargs)
private static LambdaExpression ExpresionFuncToLambda(Expression func, string name, uint nTargs)
{
ParameterExpression[] args = new ParameterExpression[nTargs];
for (int i = 0; i < nTargs; i++)
args[i] = Expression.Parameter(typeof(T));
return Expression.Lambda(Expression.Invoke(func, args), args);
return Expression.Lambda(Expression.Invoke(func, args), name, args);
}
//TODO? more general/generics
private static LambdaExpression ParseFuncTUUTToLambda<U>(Func<U, U> func)
=> ExpresionFuncToLambda(ParseFuncTUUT<U>(func), 1);
private static LambdaExpression MakeSin()
=> default(T) switch // TODO? cleaner switch
{
float => ParseFuncTUUTToLambda<float>(MathF.Sin),
double => ParseFuncTUUTToLambda<double>(Math.Sin),
_ => throw new NotImplementedException("Sinus for " + typeof(T))
};
private static LambdaExpression MakeCos()
=> default(T) switch
{
float => ParseFuncTUUTToLambda<float>(MathF.Cos),
double => ParseFuncTUUTToLambda<double>(Math.Cos),
_ => throw new NotImplementedException("Sinus for " + typeof(T))
};
private static LambdaExpression ExpresionFuncToLambda(Expression func, string name, LambdaExpression[] args_lamda, uint nTargs_fallback)
=> args_lamda == null || args_lamda.Count() == 0
? ExpresionFuncToLambda(func, name, nTargs_fallback)
: Expression.Lambda(Expression.Invoke(func, args_lamda.Select(l => l.Body)), name, args_lamda.SelectMany(l => l.Parameters));
private static Expression<Func<U, U>> ParseFuncUUToExpression<U>(Func<U, U> func)
=> (Expression<Func<U, U>>) ((x) => func(x));
private static LambdaExpression MakeSin(LambdaExpression[] args_lamda)
=> ExpresionFuncToLambda(
default(T) switch // TODO? cleaner switch
{
float => ParseFuncUUToExpression<float>(MathF.Sin),
double => ParseFuncUUToExpression<double>(Math.Sin),
_ => throw new NotImplementedException("Sinus for " + typeof(T))
},
"Sin", args_lamda, 1
);
private static LambdaExpression MakeCos(LambdaExpression[] args_lamda)
=> ExpresionFuncToLambda(
default(T) switch // TODO? cleaner switch
{
float => ParseFuncUUToExpression<float>(MathF.Cos),
double => ParseFuncUUToExpression<double>(Math.Cos),
_ => throw new NotImplementedException("Cosinus for " + typeof(T))
},
"Cos", args_lamda, 1
);
}
......@@ -262,7 +295,7 @@ public class MMTTerm
{
string kind;
virtual public LambdaExpression GetLambdaExpression()
virtual public LambdaExpression GetLambdaExpression(LambdaExpression[] args = null)
=> Expression.Lambda(Expression.Empty(), null);
}
......@@ -278,37 +311,8 @@ public OMA(MMTTerm applicant, List<MMTTerm> arguments)
this.arguments = arguments;
}
override public LambdaExpression GetLambdaExpression()
{
// local variable for each arguments
ParameterExpression[] line_variable = new ParameterExpression[arguments.Count];
// expression of computing arguments and assigning to corresponding variable
Expression[] line_expression = new Expression[arguments.Count + 1];
// unbound parameters a.k.a. all params of arguments
List<ParameterExpression> father_param = new();
for (int i = 0; i < arguments.Count; i++)
{
LambdaExpression
child_lambda = arguments[i].GetLambdaExpression();
List<ParameterExpression>
child_params = child_lambda.Parameters.ToList();
line_variable[i] = Expression.Variable(child_lambda.ReturnType);
line_expression[i] = Expression.Assign(line_variable[i], Expression.Invoke(child_lambda, child_params));
foreach (ParameterExpression arg in child_params)
father_param.Add(arg);
}
// invoke applicant with computed arguments
line_expression[arguments.Count] = Expression.Invoke(applicant.GetLambdaExpression(), line_variable);
// compile all this into LambdaExpression
return Expression.Lambda(Expression.Block(line_variable, line_expression), father_param);
}
override public LambdaExpression GetLambdaExpression(LambdaExpression[] args = null)
=> applicant.GetLambdaExpression(arguments?.Select(mmt => mmt.GetLambdaExpression()).ToArray());
}
public class OMS : MMTTerm
......@@ -321,8 +325,8 @@ public OMS(string uri)
this.uri = uri;
}
override public LambdaExpression GetLambdaExpression()
=> MMTtoLambdaExpression<float>.MakeLambdaExpression(uri);
override public LambdaExpression GetLambdaExpression(LambdaExpression[] args)
=> MMTtoLambdaExpression<float>.MakeLambdaExpression(uri, args);
}
public class OMSTR : MMTTerm
......@@ -336,7 +340,7 @@ public OMSTR(string s)
this.s = s;
}
override public LambdaExpression GetLambdaExpression()
override public LambdaExpression GetLambdaExpression(LambdaExpression[] args = null)
=> Expression.Lambda(Expression.Constant(s, typeof(string)), null);
}
......@@ -351,10 +355,11 @@ public OMF(float f)
this.f = f;
}
override public LambdaExpression GetLambdaExpression()
override public LambdaExpression GetLambdaExpression(LambdaExpression[] args = null)
=> Expression.Lambda(Expression.Constant(f, typeof(float)), null);
}
public class MMTDeclaration
{
public string label;
......@@ -362,16 +367,14 @@ public class MMTDeclaration
public static MMTDeclaration FromJson(string json)
{
MMTDeclaration mmtDecl = JsonConvert.DeserializeObject<MMTDeclaration>(json);
if (mmtDecl.label == null)
mmtDecl.label = string.Empty;
mmtDecl.label ??= string.Empty;
return mmtDecl;
}
public static string ToJson(MMTDeclaration mmtDecl)
{
if (mmtDecl.label == null)
mmtDecl.label = string.Empty;
mmtDecl.label ??= string.Empty;
string json = JsonConvert.SerializeObject(mmtDecl);
return json;
......
......@@ -12,3 +12,6 @@
//Local
[assembly: SuppressMessage("Style", "IDE0018:Inlinevariablendeklaration", Justification = "Readability", Scope = "member", Target = "~M:Math3d.GetLineSplineIntersections(UnityEngine.Vector2[],UnityEngine.Vector2[])")]
[assembly: SuppressMessage("Style", "IDE0018:Inlinevariablendeklaration", Justification = "Readability", Scope = "member", Target = "~M:Math3d.AreLineSegmentsCrossing(UnityEngine.Vector3,UnityEngine.Vector3,UnityEngine.Vector3,UnityEngine.Vector3)~System.Boolean")]
[assembly: SuppressMessage("Style", "IDE0044:Modifizierer \"readonly\" hinzufügen", Justification = "Must not be for De/Serialzer", Scope = "member", Target = "~F:JSONManager.MMTTerm.kind")]
[assembly: SuppressMessage("CodeQuality", "IDE0051:Nicht verwendete private Member entfernen", Justification = "Needed for De/Serialzer", Scope = "member", Target = "~F:JSONManager.MMTTerm.kind")]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment