Skip to content

Commit ae3f2b4

Browse files
Merge pull request #52 from delegateas/dev
Release
2 parents d85b59a + 301869b commit ae3f2b4

11 files changed

Lines changed: 351 additions & 4 deletions

File tree

ExpressionEngine/FlowRunnerDependencyExtension.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using ExpressionEngine.Functions.Implementations.ConversionFunctions;
44
using ExpressionEngine.Functions.Implementations.LogicalComparisonFunctions;
55
using ExpressionEngine.Functions.Implementations.StringFunctions;
6+
using ExpressionEngine.Functions.Math;
67
using Microsoft.Extensions.DependencyInjection;
78

89
namespace ExpressionEngine
@@ -18,6 +19,7 @@ public static void AddExpressionEngine(this IServiceCollection services)
1819
AddCollectionFunction(services);
1920
AddConversionFunction(services);
2021
AddLogicalComparisonFunctions(services);
22+
AddMathFunctions(services);
2123

2224
services.AddTransient<IFunction, LengthFunction>();
2325
services.AddTransient<IFunction, GreaterFunction>();
@@ -80,5 +82,18 @@ private static void AddLogicalComparisonFunctions(IServiceCollection services)
8082
services.AddTransient<IFunction, NotFunction>();
8183
services.AddTransient<IFunction, OrFunction>();
8284
}
85+
86+
private static void AddMathFunctions(IServiceCollection services)
87+
{
88+
services.AddTransient<IFunction, AndFunction>();
89+
services.AddTransient<IFunction, DivFunction>();
90+
services.AddTransient<IFunction, MaxFunction>();
91+
services.AddTransient<IFunction, MinFunction>();
92+
services.AddTransient<IFunction, ModFunction>();
93+
services.AddTransient<IFunction, MulFunction>();
94+
services.AddTransient<IFunction, RandFunction>();
95+
services.AddTransient<IFunction, RangeFunction>();
96+
services.AddTransient<IFunction, SubFunction>();
97+
}
8398
}
8499
}

ExpressionEngine/Functions/Math/AddFunction.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ public override ValueTask<ValueContainer> ExecuteFunction(params ValueContainer[
1414
{
1515
if (parameters.Length != 2)
1616
{
17-
throw new InvalidTemplateException("Paramters count does not match expected");
17+
throw new InvalidTemplateException(
18+
"The template language function 'add' expects two numeric parameters: " +
19+
"the first summand as the first parameter and the second summand as the second parameter.");
1820
}
1921

20-
var first = parameters[0].GetValue<float>();
21-
var second = parameters[1].GetValue<float>();
22+
var first = parameters[0].GetValue<double>();
23+
var second = parameters[1].GetValue<double>();
2224

2325
return new ValueTask<ValueContainer>(new ValueContainer(first + second));
2426
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System.Threading.Tasks;
2+
using ExpressionEngine.Functions.Base;
3+
using ExpressionEngine.Functions.CustomException;
4+
5+
namespace ExpressionEngine.Functions.Math
6+
{
7+
public class DivFunction : Function
8+
{
9+
public DivFunction() : base("div")
10+
{
11+
}
12+
13+
public override ValueTask<ValueContainer> ExecuteFunction(params ValueContainer[] parameters)
14+
{
15+
if (parameters.Length != 2)
16+
{
17+
throw new InvalidTemplateException(
18+
"The template language function 'div' expects two numeric parameters: " +
19+
"the dividend as the first parameter and the divisor as the second parameter");
20+
}
21+
22+
var first = parameters[0].GetValue<double>();
23+
var second = parameters[1].GetValue<double>();
24+
25+
if (second == 0)
26+
{
27+
throw new ExpressionEngineException(
28+
"Attempt to divide an integral or decimal value by zero in function 'div'.");
29+
}
30+
31+
return new ValueTask<ValueContainer>(new ValueContainer(first / second));
32+
}
33+
}
34+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using System.Threading.Tasks;
4+
using ExpressionEngine.Functions.Base;
5+
using ExpressionEngine.Functions.CustomException;
6+
7+
namespace ExpressionEngine.Functions.Math
8+
{
9+
public class MaxFunction : Function
10+
{
11+
public MaxFunction() : base("max")
12+
{
13+
}
14+
15+
public override ValueTask<ValueContainer> ExecuteFunction(params ValueContainer[] parameters)
16+
{
17+
if (parameters.Length == 0)
18+
{
19+
throw new InvalidTemplateException(
20+
"he template language function 'max' expects either an array of numbers or a comma " +
21+
"separated list of numbers as its parameters. The function was invoked with no parameters");
22+
}
23+
24+
if (parameters[0].Type() == ValueType.Array)
25+
{
26+
if (parameters.Length > 1)
27+
{
28+
throw new InvalidTemplateException(
29+
$"The template language function 'max' expects all of its parameters to be either " +
30+
$"integer or decimal numbers. Found invalid parameter types: '{parameters[1].Type()}'.");
31+
}
32+
33+
return new ValueTask<ValueContainer>(
34+
new ValueContainer(parameters[0].GetValue<IEnumerable<ValueContainer>>().Max()));
35+
}
36+
37+
var firstNonNumber =
38+
parameters.FirstOrDefault(x => x.Type() != ValueType.Float || x.Type() != ValueType.Integer);
39+
40+
if (firstNonNumber != null)
41+
{
42+
throw new InvalidTemplateException(
43+
$"The template language function 'max' expects all of its parameters to be either " +
44+
$"integer or decimal numbers. Found invalid parameter types: '{firstNonNumber.Type()}'.");
45+
}
46+
47+
return new ValueTask<ValueContainer>(parameters.Max());
48+
}
49+
}
50+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using System.Threading.Tasks;
4+
using ExpressionEngine.Functions.Base;
5+
using ExpressionEngine.Functions.CustomException;
6+
7+
namespace ExpressionEngine.Functions.Math
8+
{
9+
public class MinFunction : Function
10+
{
11+
public MinFunction() : base("min")
12+
{
13+
}
14+
15+
public override ValueTask<ValueContainer> ExecuteFunction(params ValueContainer[] parameters)
16+
{
17+
if (parameters.Length == 0)
18+
{
19+
throw new InvalidTemplateException(
20+
"he template language function 'min' expects either an array of numbers or a comma " +
21+
"separated list of numbers as its parameters. The function was invoked with no parameters");
22+
}
23+
24+
if (parameters[0].Type() == ValueType.Array)
25+
{
26+
if (parameters.Length > 1)
27+
{
28+
throw new InvalidTemplateException(
29+
$"The template language function 'min' expects all of its parameters to be either " +
30+
$"integer or decimal numbers. Found invalid parameter types: '{parameters[1].Type()}'.");
31+
}
32+
33+
return new ValueTask<ValueContainer>(
34+
new ValueContainer(parameters[0].GetValue<IEnumerable<ValueContainer>>().Min()));
35+
}
36+
37+
var firstNonNumber =
38+
parameters.FirstOrDefault(x => x.Type() != ValueType.Float || x.Type() != ValueType.Integer);
39+
40+
if (firstNonNumber != null)
41+
{
42+
throw new InvalidTemplateException(
43+
$"The template language function 'min' expects all of its parameters to be either " +
44+
$"integer or decimal numbers. Found invalid parameter types: '{firstNonNumber.Type()}'.");
45+
}
46+
47+
return new ValueTask<ValueContainer>(parameters.Min());
48+
}
49+
}
50+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System.Threading.Tasks;
2+
using ExpressionEngine.Functions.Base;
3+
using ExpressionEngine.Functions.CustomException;
4+
5+
namespace ExpressionEngine.Functions.Math
6+
{
7+
public class ModFunction : Function
8+
{
9+
public ModFunction() : base("mod")
10+
{
11+
}
12+
13+
public override ValueTask<ValueContainer> ExecuteFunction(params ValueContainer[] parameters)
14+
{
15+
if (parameters.Length != 2)
16+
{
17+
throw new InvalidTemplateException(
18+
"The template language function 'mod' expects two numeric parameters: " +
19+
"the dividend as the first parameter and the divisor as the second parameter");
20+
}
21+
22+
var first = parameters[0].GetValue<double>();
23+
var second = parameters[1].GetValue<double>();
24+
25+
return new ValueTask<ValueContainer>(new ValueContainer(first % second));
26+
}
27+
}
28+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System.Threading.Tasks;
2+
using ExpressionEngine.Functions.Base;
3+
using ExpressionEngine.Functions.CustomException;
4+
5+
namespace ExpressionEngine.Functions.Math
6+
{
7+
public class MulFunction : Function
8+
{
9+
public MulFunction() : base("mul")
10+
{
11+
}
12+
13+
public override ValueTask<ValueContainer> ExecuteFunction(params ValueContainer[] parameters)
14+
{
15+
if (parameters.Length != 2)
16+
{
17+
throw new InvalidTemplateException(
18+
"The template language function 'mul' expects two numeric parameters: " +
19+
"the first multiplicand as the first parameter and the second multiplicand as the second parameter");
20+
}
21+
22+
var first = parameters[0].GetValue<double>();
23+
var second = parameters[1].GetValue<double>();
24+
25+
return new ValueTask<ValueContainer>(new ValueContainer(first * second));
26+
}
27+
}
28+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using ExpressionEngine.Functions.Base;
4+
using ExpressionEngine.Functions.CustomException;
5+
6+
namespace ExpressionEngine.Functions.Math
7+
{
8+
public class RandFunction : Function
9+
{
10+
public RandFunction() : base("rand")
11+
{
12+
}
13+
14+
public override ValueTask<ValueContainer> ExecuteFunction(params ValueContainer[] parameters)
15+
{
16+
if (parameters.Length != 2)
17+
{
18+
throw new InvalidTemplateException(
19+
"The template language function 'rand' expects two integer parameters: an inclusive minimum " +
20+
"of the range as the first parameter and an inclusive maximum of the range as the second parameter");
21+
}
22+
23+
var first = parameters[0].GetValue<int>();
24+
var second = parameters[1].GetValue<int>();
25+
26+
var rand = new Random();
27+
28+
return new ValueTask<ValueContainer>(new ValueContainer(rand.Next(first, second)));
29+
}
30+
}
31+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System.Linq;
2+
using System.Threading.Tasks;
3+
using ExpressionEngine.Functions.Base;
4+
using ExpressionEngine.Functions.CustomException;
5+
6+
namespace ExpressionEngine.Functions.Math
7+
{
8+
public class RangeFunction : Function
9+
{
10+
public RangeFunction() : base("range")
11+
{
12+
}
13+
14+
public override ValueTask<ValueContainer> ExecuteFunction(params ValueContainer[] parameters)
15+
{
16+
if (parameters.Length != 2)
17+
{
18+
throw new InvalidTemplateException(
19+
"The template language function 'range' expects two integer parameters: an inclusive start" +
20+
" index of the range as the first parameter and a count of integers to return as the second parameter");
21+
}
22+
23+
var startIndex = parameters[0].GetValue<int>();
24+
var count = parameters[1].GetValue<int>();
25+
26+
if (count > 100000 || startIndex >= int.MaxValue - 100000)
27+
{
28+
throw new InvalidTemplateException(
29+
"The template language function 'range' parameters are out of range: 'count' must be a positive " +
30+
"integer no larger than '100000' and the sum of 'start index' and 'count' must be no larger than 2147483647");
31+
}
32+
33+
return new ValueTask<ValueContainer>(
34+
new ValueContainer(Enumerable.Range(startIndex, count).Select(x => new ValueContainer(x))));
35+
}
36+
}
37+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System.Threading.Tasks;
2+
using ExpressionEngine.Functions.Base;
3+
using ExpressionEngine.Functions.CustomException;
4+
5+
namespace ExpressionEngine.Functions.Math
6+
{
7+
public class SubFunction : Function
8+
{
9+
public SubFunction() : base("sub")
10+
{
11+
}
12+
13+
public override ValueTask<ValueContainer> ExecuteFunction(params ValueContainer[] parameters)
14+
{
15+
if (parameters.Length != 2)
16+
{
17+
throw new InvalidTemplateException(
18+
"The template language function 'sub' expects two numeric parameters: " +
19+
"the minuend as the first parameter and the subtrahend as the second parameter");
20+
}
21+
22+
var first = parameters[0].GetValue<double>();
23+
var second = parameters[1].GetValue<double>();
24+
25+
return new ValueTask<ValueContainer>(new ValueContainer(first - second));
26+
}
27+
}
28+
}

0 commit comments

Comments
 (0)