Skip to content

Commit 3e9a765

Browse files
committed
Add Min and Max functions
1 parent 1298035 commit 3e9a765

File tree

3 files changed

+56
-0
lines changed

3 files changed

+56
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ Creation of custom variables is supported. Variable name may contains only engli
7171
| ---- | --------- | ----------- |
7272
| NOT | NOT(TRUE) | Returns FALSE if argument is true, otherwise TRUE |
7373
| IF | IF(n < 5, 5, n < 25, 25, 50) | Returns the second argument if the first argument is true, returns the fourth argument if the third argument is true, and so on. Otherwise, returns the last argument. Odd number of arguments required |
74+
| MIN | MIN(0, 1, ...) | Returns smallest argument |
75+
| MAX | MAX(0, 1, ...) | Returns largest argument |
7476

7577
## How to Install
7678
Minimal Unity Version is 2020.1.

Runtime/ExpressionParser.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ select MakeUnary(Negate, fact)
157157
private T Not(T v) => IsTrue(v) ? False : True;
158158
private T And(T a, T b) => IsTrue(a) ? b : a;
159159
private T Or(T a, T b) => IsTrue(a) ? a : b;
160+
private T Min(T a, T b) => IsTrue(GreaterThan(a, b)) ? b : a;
161+
private T Max(T a, T b) => IsTrue(GreaterThan(b, a)) ? b : a;
160162

161163
private delegate Expression<T> ExprBuilder(ExpresionContext<T> context);
162164

@@ -171,6 +173,12 @@ private ExprBuilder MakeFunction(string name, List<ExprBuilder> parameterBuilder
171173
case "NOT":
172174
return MakeFunction1(Not);
173175

176+
case "MIN":
177+
return MakeFunctionFold(Min);
178+
179+
case "MAX":
180+
return MakeFunctionFold(Max);
181+
174182
case "IF":
175183
if (parameterBuilders.Count < 3 ||
176184
parameterBuilders.Count % 2 != 1)
@@ -220,6 +228,35 @@ ExprBuilder MakeFunction1(Func<T, T> func)
220228
return () => func(inner.Invoke());
221229
};
222230
}
231+
232+
ExprBuilder MakeFunctionFold(Func<T, T, T> func)
233+
{
234+
if (parameterBuilders.Count < 1)
235+
{
236+
throw new FunctionNotDefinedException(name, "Wrong parameters count");
237+
}
238+
239+
return context =>
240+
{
241+
var inner = new List<Expression<T>>();
242+
243+
for (var i = 0; i < parameterBuilders.Count; i++)
244+
{
245+
inner.Add(parameterBuilders[i].Invoke(context));
246+
}
247+
248+
return () =>
249+
{
250+
var result = inner[0].Invoke();
251+
for (var i = 1; i < inner.Count; i++)
252+
{
253+
result = func(result, inner[i].Invoke());
254+
}
255+
256+
return result;
257+
};
258+
};
259+
}
223260
}
224261

225262
private static ExprBuilder MakeUnary(UnaryFunc func, ExprBuilder innerBuilder)

Tests/ParserTests.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ public class ParserTests
4242
[TestCase("NOT(-5)", ExpectedResult = 0)]
4343
[TestCase("NOT(5)", ExpectedResult = 0)]
4444
[TestCase("NOT(NOT(0))", ExpectedResult = 0)]
45+
// MIN
46+
[TestCase("MIN(0, 0)", ExpectedResult = 0)]
47+
[TestCase("MIN(0, 1)", ExpectedResult = 0)]
48+
[TestCase("MIN(-5, 5)", ExpectedResult = -5)]
49+
[TestCase("MIN(5, 4, 7, 3, 4)", ExpectedResult = 3)]
50+
// MAX
51+
[TestCase("MAX(0, 0)", ExpectedResult = 0)]
52+
[TestCase("MAX(0, 1)", ExpectedResult = 1)]
53+
[TestCase("MAX(-5, 5)", ExpectedResult = 5)]
54+
[TestCase("MAX(5, 4, 7, 3, 4)", ExpectedResult = 7)]
4555
// AND
4656
[TestCase("0 AND 0", ExpectedResult = 0)]
4757
[TestCase("0 AND 1", ExpectedResult = 0)]
@@ -142,6 +152,13 @@ public void Parse_Compare_Invalid()
142152
Assert.Throws<ParseException>(() => Compile("0 = 0 != 0", null));
143153
}
144154

155+
[Test]
156+
public void Parse_MinMax_Invalid()
157+
{
158+
Assert.Throws<ParseException>(() => Compile("MIN()", null));
159+
Assert.Throws<ParseException>(() => Compile("MAX()", null));
160+
}
161+
145162
[Test]
146163
public void Parse_If()
147164
{

0 commit comments

Comments
 (0)