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 ...@@ -59,11 +59,14 @@ public static class MMTURIs
public static class MMTtoLambdaExpression<T> 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 // TODO: Populate Dictionaries
#region ExpressionDictionaries #region ExpressionDictionaries
private static Dictionary<string, Func<LambdaExpression>> MMTtoLambdaMaker = new() private static readonly Dictionary<string, Func<LambdaExpression[], LambdaExpression>> MMTtoLambdaMaker = new()
{ {
{ "sin", { "sin",
MakeSin}, MakeSin},
...@@ -71,7 +74,7 @@ public static class MMTtoLambdaExpression<T> ...@@ -71,7 +74,7 @@ public static class MMTtoLambdaExpression<T>
MakeCos}, MakeCos},
}; };
private static Dictionary<string, ExpressionType> MMTtoBinaryExpressionType = new() private static readonly Dictionary<string, ExpressionType> MMTtoBinaryExpressionType = new()
{ {
{ "Add", { "Add",
ExpressionType.Add}, ExpressionType.Add},
...@@ -149,10 +152,14 @@ public static class MMTtoLambdaExpression<T> ...@@ -149,10 +152,14 @@ public static class MMTtoLambdaExpression<T>
ExpressionType.SubtractChecked}, ExpressionType.SubtractChecked},
}; };
private static Dictionary<string, ExpressionType> MMTtoUnaryExpressionType = new() private static readonly Dictionary<string, ExpressionType> MMTtoUnaryExpressionType = new()
{ {
//{ "Constant", // Not Unary //{ "Constant", // Not Unary
// ExpressionType.Constant}, // ExpressionType.Constant},
{ "Convert",
ExpressionType.Convert},
{ "ConvertChecked",
ExpressionType.ConvertChecked},
{ "Decrement", { "Decrement",
ExpressionType.Decrement}, ExpressionType.Decrement},
{ "Increment", { "Increment",
...@@ -179,71 +186,97 @@ public static class MMTtoLambdaExpression<T> ...@@ -179,71 +186,97 @@ public static class MMTtoLambdaExpression<T>
#endregion ExpressionDictionaries #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)) if (MMTtoUnaryExpressionType.TryGetValue(URI, out var unnary_type))
{ {
ParameterExpression[] args = new ParameterExpression[] { if (args_lamda == null) {
Expression.Parameter(typeof(T)) ParameterExpression[] args = new ParameterExpression[] {
}; Expression.Parameter(typeof(T), "PNamed_" + (++param_counter).ToString()),
return Expression.Lambda(Expression.MakeUnary(unnary_type, args[0], typeof(T)), args); };
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)) else if (MMTtoBinaryExpressionType.TryGetValue(URI, out var binary_type))
{ {
ParameterExpression[] args = new ParameterExpression[] { if (args_lamda == null) {
Expression.Parameter(typeof(T)), ParameterExpression[] args = new ParameterExpression[] {
Expression.Parameter(typeof(T)) 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); };
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)) 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 + "\""); throw new NotImplementedException("Could not map URI: \"" + URI + "\"");
} }
private static Expression<Func<T, T>> ParseFuncTUUT<U>(Func<U,U> func) private static LambdaExpression ExpresionFuncToLambda(Expression func, string name, uint nTargs)
=> (T x) =>
(T) Convert.ChangeType(
func(
(U) Convert.ChangeType(
x,
typeof(U)
)
),
typeof(T)
);
private static LambdaExpression ExpresionFuncToLambda(Expression func, uint nTargs)
{ {
ParameterExpression[] args = new ParameterExpression[nTargs]; ParameterExpression[] args = new ParameterExpression[nTargs];
for (int i = 0; i < nTargs; i++) for (int i = 0; i < nTargs; i++)
args[i] = Expression.Parameter(typeof(T)); 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 ExpresionFuncToLambda(Expression func, string name, LambdaExpression[] args_lamda, uint nTargs_fallback)
private static LambdaExpression ParseFuncTUUTToLambda<U>(Func<U, U> func) => args_lamda == null || args_lamda.Count() == 0
=> ExpresionFuncToLambda(ParseFuncTUUT<U>(func), 1); ? 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 LambdaExpression MakeSin()
=> default(T) switch // TODO? cleaner switch private static Expression<Func<U, U>> ParseFuncUUToExpression<U>(Func<U, U> func)
{ => (Expression<Func<U, U>>) ((x) => func(x));
float => ParseFuncTUUTToLambda<float>(MathF.Sin),
double => ParseFuncTUUTToLambda<double>(Math.Sin), private static LambdaExpression MakeSin(LambdaExpression[] args_lamda)
_ => throw new NotImplementedException("Sinus for " + typeof(T)) => ExpresionFuncToLambda(
}; default(T) switch // TODO? cleaner switch
{
private static LambdaExpression MakeCos() float => ParseFuncUUToExpression<float>(MathF.Sin),
=> default(T) switch double => ParseFuncUUToExpression<double>(Math.Sin),
{ _ => throw new NotImplementedException("Sinus for " + typeof(T))
float => ParseFuncTUUTToLambda<float>(MathF.Cos), },
double => ParseFuncTUUTToLambda<double>(Math.Cos), "Sin", args_lamda, 1
_ => throw new NotImplementedException("Sinus for " + typeof(T)) );
};
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 ...@@ -262,7 +295,7 @@ public class MMTTerm
{ {
string kind; string kind;
virtual public LambdaExpression GetLambdaExpression() virtual public LambdaExpression GetLambdaExpression(LambdaExpression[] args = null)
=> Expression.Lambda(Expression.Empty(), null); => Expression.Lambda(Expression.Empty(), null);
} }
...@@ -278,37 +311,8 @@ public OMA(MMTTerm applicant, List<MMTTerm> arguments) ...@@ -278,37 +311,8 @@ public OMA(MMTTerm applicant, List<MMTTerm> arguments)
this.arguments = arguments; this.arguments = arguments;
} }
override public LambdaExpression GetLambdaExpression() override public LambdaExpression GetLambdaExpression(LambdaExpression[] args = null)
{ => applicant.GetLambdaExpression(arguments?.Select(mmt => mmt.GetLambdaExpression()).ToArray());
// 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);
}
} }
public class OMS : MMTTerm public class OMS : MMTTerm
...@@ -321,8 +325,8 @@ public OMS(string uri) ...@@ -321,8 +325,8 @@ public OMS(string uri)
this.uri = uri; this.uri = uri;
} }
override public LambdaExpression GetLambdaExpression() override public LambdaExpression GetLambdaExpression(LambdaExpression[] args)
=> MMTtoLambdaExpression<float>.MakeLambdaExpression(uri); => MMTtoLambdaExpression<float>.MakeLambdaExpression(uri, args);
} }
public class OMSTR : MMTTerm public class OMSTR : MMTTerm
...@@ -336,7 +340,7 @@ public OMSTR(string s) ...@@ -336,7 +340,7 @@ public OMSTR(string s)
this.s = s; this.s = s;
} }
override public LambdaExpression GetLambdaExpression() override public LambdaExpression GetLambdaExpression(LambdaExpression[] args = null)
=> Expression.Lambda(Expression.Constant(s, typeof(string)), null); => Expression.Lambda(Expression.Constant(s, typeof(string)), null);
} }
...@@ -351,10 +355,11 @@ public OMF(float f) ...@@ -351,10 +355,11 @@ public OMF(float f)
this.f = f; this.f = f;
} }
override public LambdaExpression GetLambdaExpression() override public LambdaExpression GetLambdaExpression(LambdaExpression[] args = null)
=> Expression.Lambda(Expression.Constant(f, typeof(float)), null); => Expression.Lambda(Expression.Constant(f, typeof(float)), null);
} }
public class MMTDeclaration public class MMTDeclaration
{ {
public string label; public string label;
...@@ -362,16 +367,14 @@ public class MMTDeclaration ...@@ -362,16 +367,14 @@ public class MMTDeclaration
public static MMTDeclaration FromJson(string json) public static MMTDeclaration FromJson(string json)
{ {
MMTDeclaration mmtDecl = JsonConvert.DeserializeObject<MMTDeclaration>(json); MMTDeclaration mmtDecl = JsonConvert.DeserializeObject<MMTDeclaration>(json);
if (mmtDecl.label == null) mmtDecl.label ??= string.Empty;
mmtDecl.label = string.Empty;
return mmtDecl; return mmtDecl;
} }
public static string ToJson(MMTDeclaration mmtDecl) public static string ToJson(MMTDeclaration mmtDecl)
{ {
if (mmtDecl.label == null) mmtDecl.label ??= string.Empty;
mmtDecl.label = string.Empty;
string json = JsonConvert.SerializeObject(mmtDecl); string json = JsonConvert.SerializeObject(mmtDecl);
return json; return json;
......
...@@ -12,3 +12,6 @@ ...@@ -12,3 +12,6 @@
//Local //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.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", "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