Closed victoriatolls closed 5 years ago
Hi all,
This broke some functionality for us because we have our own implementations of Min
and Max
in our context, which have now been overshadowed by these built-in min and max.
As a solution, I propose we move them after the keywords and after the context lookup, something like the snippet at the end of this comment.
My reasoning:
Min
, Max
and Pow
are not reserved C# keywords. So we shouldn't short-circuit them like we do with if
and in
(we can't expect context users not to override them).double
and they cannot be overridden. (Consider something like Min(pointA, pointB)
where points A and B are custom coordinate objects with custom Min
implementation -- this is our case).My proposal is something like:
string functionName = function.Identifier.Name.ToLowerInvariant();
if (functionName == "if") {
_result = L.Expression.Condition(args[0], args[1], args[2]);
return;
} else if (functionName == "in") {
var items = L.Expression.NewArrayInit(args[0].Type, new ArraySegment<L.Expression>(args, 1, args.Length - 1));
var smi = typeof (Array).GetRuntimeMethod("IndexOf", new[] { typeof(Array), typeof(object) });
var r = L.Expression.Call(smi, L.Expression.Convert(items, typeof(Array)), L.Expression.Convert(args[0], typeof(object)));
_result = L.Expression.GreaterThanOrEqual(r, L.Expression.Constant(0));
return;
}
//"FindMethod" would be changed so it would just return null instead of throwing "method not found".
var mi = FindMethod(function.Identifier.Name, args);
if (mi != null) {
_result = L.Expression.Call(_context, mi.BaseMethodInfo, mi.PreparedArguments);
return;
}
// default function implementation like min, max, pow, and any other in the future.
switch (functionName) {
case "min":
var min_arg0 = L.Expression.Convert(args[0], typeof(double));
var min_arg1 = L.Expression.Convert(args[1], typeof(double));
_result = L.Expression.Condition(L.Expression.LessThan(min_arg0, min_arg1), min_arg0, min_arg1);
break;
case "max":
var max_arg0 = L.Expression.Convert(args[0], typeof(double));
var max_arg1 = L.Expression.Convert(args[1], typeof(double));
_result = L.Expression.Condition(L.Expression.GreaterThan(max_arg0, max_arg1), max_arg0, max_arg1);
break;
case "pow":
var pow_arg0 = L.Expression.Convert(args[0], typeof(double));
var pow_arg1 = L.Expression.Convert(args[1], typeof(double));
_result = L.Expression.Power(pow_arg0, pow_arg1);
break;
default:
throw new Exception($"method not found: {functionName}");
}
@sklose I understand you're only passively maintaining the repo at the moment so I'm happy to prepare this, add tests and open a PR if you concur with the above.
We've only just found out about this because we've only recently upgraded to the latest version. We had to rollback to a version just before this one though because of the breaking change.
Thanks all,
fadulalla
Hi @fadulalla
this sounds very reasonable to me. Happy to merge a PR with those changes.
Best, Sebastian
Hi @victoriatolls,
thanks for submitting this PR. Can you add a few unit tests for the new Min/Max/Pow functions?
Best, Sebastian