Skip to content

Commit 3f3ff05

Browse files
Merge branch 'dev' into main
2 parents ae3f2b4 + 80a14e6 commit 3f3ff05

35 files changed

+1033
-115
lines changed

.github/workflows/build.yml

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,60 @@ jobs:
3434
- uses: actions/setup-dotnet@v1
3535
with:
3636
dotnet-version: '5.0.x'
37-
37+
3838
- name: Cleaning
3939
run: dotnet clean
4040

4141
- name: Restore NuGet packages
4242
run: dotnet restore ExpressionEngine.sln
4343

4444
- name: Build solution
45-
run: dotnet build -o ../build/${{ matrix.dotnet }} -c Release --no-restore -m:1 -f ${{ matrix.dotnet }}
45+
run: dotnet build -o build/${{ matrix.dotnet }} -c Release --no-restore -m:1 -f ${{ matrix.dotnet }}
46+
47+
- name: Cache build artifacts
48+
uses: actions/cache@v2
49+
with:
50+
path: build/${{ matrix.dotnet }}
51+
key: ${{ runner.os }}-build-${{ matrix.dotnet }}
52+
53+
publish:
54+
runs-on: windows-latest
55+
name: Generate docs and publish artifacts
56+
needs: ['build']
57+
steps:
58+
- name: Get cache - net5.0
59+
uses: actions/cache@v2
60+
with:
61+
path: build/net5.0
62+
key: ${{ runner.os }}-build-net5.0
63+
64+
- name: Get cache - netcoreapp3.1
65+
uses: actions/cache@v2
66+
with:
67+
path: build/netcoreapp3.1
68+
key: ${{ runner.os }}-build-netcoreapp3.1
69+
70+
- uses: actions/setup-dotnet@v1
71+
with:
72+
dotnet-version: '5.0.x'
73+
74+
- name: Install Xml to Markdown tool
75+
run: dotnet new tool-manifest && dotnet tool install EAVFW.Extensions.Docs.TransformToMarkdown
76+
77+
- name: Generate docs
78+
run: dotnet tool run tomd --input build/net5.0/ExpressionEngine.xml --output Documentation.md
4679

4780
- name: Archive build to artifacts
48-
uses: actions/upload-artifact@v2
81+
uses: actions/upload-artifact@v2.3.1
4982
with:
5083
name: build
5184
path: |
52-
build/${{ matrix.dotnet }}/*
85+
build/netcoreapp3.1/
86+
build/net5.0/
5387
retention-days: 5
88+
89+
- name: Archive documentation to artifacts
90+
uses: actions/upload-artifact@v2.3.1
91+
with:
92+
name: Documentation
93+
path: Documentation.md

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636

3737
- uses: actions/setup-node@v2
3838
with:
39-
node-version: '14'
39+
node-version: '16'
4040

4141
- name: Add plugin for conventional commits
4242
run: npm install conventional-changelog-conventionalcommits

.github/workflows/todo.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ on:
44
push:
55
branches:
66
- 'dev'
7+
- 'main'
78
- 'feature/**'
89

910
jobs:
1011
build:
1112
runs-on: "ubuntu-latest"
1213
steps:
13-
- uses: "actions/checkout@master"
14+
- name: Checkout repo
15+
uses: actions/checkout@v2
1416
- name: "TODO to Issue"
1517
uses: "alstr/todo-to-issue-action@v2.4"
1618
id: "todo"

ExpressionEngine.sln

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,27 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExpressionEngine", "ExpressionEngine\ExpressionEngine.csproj", "{95AD0C25-9C6D-41EE-AB8C-195EBB00333F}"
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.0.31912.275
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExpressionEngine", "ExpressionEngine\ExpressionEngine.csproj", "{95AD0C25-9C6D-41EE-AB8C-195EBB00333F}"
47
EndProject
5-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{8C11682D-1511-471B-92CF-464B560E1F03}"
8+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", "{8C11682D-1511-471B-92CF-464B560E1F03}"
69
EndProject
710
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6982C930-BF5B-4F6A-91CF-6C77E67DCF22}"
811
ProjectSection(SolutionItems) = preProject
912
.gitignore = .gitignore
10-
README.md = README.md
1113
CONTRIBUTING.md = CONTRIBUTING.md
14+
README.md = README.md
15+
EndProjectSection
16+
EndProject
17+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{D17875EE-F716-4AEF-9F13-7B4FFEFF1479}"
18+
EndProject
19+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{EC1D3541-2A35-40FD-BCFC-7A1C35F22503}"
20+
ProjectSection(SolutionItems) = preProject
21+
.github\workflows\.releaserc = .github\workflows\.releaserc
22+
.github\workflows\build.yml = .github\workflows\build.yml
23+
.github\workflows\release.yml = .github\workflows\release.yml
24+
.github\workflows\todo.yml = .github\workflows\todo.yml
1225
EndProjectSection
1326
EndProject
1427
Global
@@ -26,4 +39,13 @@ Global
2639
{8C11682D-1511-471B-92CF-464B560E1F03}.Release|Any CPU.ActiveCfg = Release|Any CPU
2740
{8C11682D-1511-471B-92CF-464B560E1F03}.Release|Any CPU.Build.0 = Release|Any CPU
2841
EndGlobalSection
42+
GlobalSection(SolutionProperties) = preSolution
43+
HideSolutionNode = FALSE
44+
EndGlobalSection
45+
GlobalSection(NestedProjects) = preSolution
46+
{EC1D3541-2A35-40FD-BCFC-7A1C35F22503} = {D17875EE-F716-4AEF-9F13-7B4FFEFF1479}
47+
EndGlobalSection
48+
GlobalSection(ExtensibilityGlobals) = postSolution
49+
SolutionGuid = {80DA8603-0FA5-4110-9168-256EC3FDDCA7}
50+
EndGlobalSection
2951
EndGlobal

ExpressionEngine/ExpressionEngine.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
<Authors>Delegate A/S,thygesteffensen</Authors>
88
<PackageDescription>Expression Engine for Power Automate expressions written in C# using Sprache.net!</PackageDescription>
99
<RepositoryUrl>https://github.com/delegateas/ExpressionEngine</RepositoryUrl>
10+
11+
<GenerateDocumentationFile>true</GenerateDocumentationFile>
1012
</PropertyGroup>
1113

1214
<ItemGroup>

ExpressionEngine/ExpressionGrammar.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ public ExpressionGrammar(IEnumerable<IFunction> functions)
2828
constString => new ConstantRule(new ValueContainer(constString, true))
2929
);
3030

31+
Parser<IRule> decimalInvariant =
32+
Parse.DecimalInvariant.Select(x => new ConstantRule(new ValueContainer(x, true)));
33+
34+
Parser<IRule> number = decimalInvariant.Or(integer);
35+
3136
Parser<string> simpleString =
3237
Parse.AnyChar.Except(Parse.Char('@')).AtLeastOnce().Text();
3338

@@ -71,7 +76,7 @@ from index in Parse.AnyChar.Except(
7176
select new IndexRule(new StringLiteralRule(new ValueContainer(index)), nll);
7277

7378
Parser<IRule> argument =
74-
from arg in Parse.Ref(() => _method.Or(stringLiteral).Or(integer).Or(boolean))
79+
from arg in Parse.Ref(() => _method.Or(stringLiteral).Or(number).Or(boolean))
7580
select arg;
7681

7782
Parser<IOption<IEnumerable<IRule>>> arguments =
@@ -106,13 +111,11 @@ from indexes in bracketIndices.Or(dotIndices).Many()
106111
from t in simpleString.Or(allowedCharacters).Many()
107112
select string.Concat(t);
108113

109-
Parser<Task<ValueContainer>> joinedString =
110-
from e in (
111-
from preFix in allowedString
112-
from exp in enclosedExpression.Optional()
113-
select exp.IsEmpty ? preFix : preFix + exp.Get())
114-
.Many()
115-
select Task.FromResult(new ValueContainer(string.Concat(e)));
114+
Parser<Task<ValueContainer>> joinedString = allowedString
115+
.SelectMany(preFix => enclosedExpression.Optional(),
116+
async (preFix, exp) => exp.IsEmpty ? preFix : preFix + await exp.Get())
117+
.Many()
118+
.Select(async e => await Task.FromResult(new ValueContainer(string.Concat(await Task.WhenAll(e)))));
116119

117120
_input = expression.Or(joinedString);
118121
}

ExpressionEngine/FlowRunnerDependencyExtension.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ private static void AddConversionFunction(IServiceCollection services)
6868
services.AddTransient<IFunction, CreateArrayFunction>();
6969
services.AddTransient<IFunction, DataUriFunction>();
7070
services.AddTransient<IFunction, DataUriToBinaryFunction>();
71+
services.AddTransient<IFunction, FloatFunction>();
72+
services.AddTransient<IFunction, IntFunction>();
7173
}
7274

7375
private static void AddLogicalComparisonFunctions(IServiceCollection services)
@@ -85,7 +87,7 @@ private static void AddLogicalComparisonFunctions(IServiceCollection services)
8587

8688
private static void AddMathFunctions(IServiceCollection services)
8789
{
88-
services.AddTransient<IFunction, AndFunction>();
90+
services.AddTransient<IFunction, AddFunction>();
8991
services.AddTransient<IFunction, DivFunction>();
9092
services.AddTransient<IFunction, MaxFunction>();
9193
services.AddTransient<IFunction, MinFunction>();
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using ExpressionEngine.Functions.Base;
4+
using ExpressionEngine.Functions.CustomException;
5+
6+
namespace ExpressionEngine.Functions.Implementations.ConversionFunctions
7+
{
8+
public class FloatFunction : Function
9+
{
10+
public FloatFunction() : base("float")
11+
{
12+
}
13+
14+
public override ValueTask<ValueContainer> ExecuteFunction(params ValueContainer[] parameters)
15+
{
16+
if (parameters.Length != 1)
17+
{
18+
throw new ArgumentError(parameters.Length > 1 ? "Too many arguments" : "Too few arguments");
19+
}
20+
21+
switch (parameters[0].Type())
22+
{
23+
case ValueType.String:
24+
if (Double.TryParse(parameters[0].GetValue<string>(), out double doubleValue))
25+
{
26+
return new ValueTask<ValueContainer>(new ValueContainer(doubleValue));
27+
}
28+
else if (Boolean.TryParse(parameters[0].GetValue<string>(), out bool boolVal))
29+
{
30+
if (boolVal)
31+
return new ValueTask<ValueContainer>(new ValueContainer(1));
32+
else
33+
return new ValueTask<ValueContainer>(new ValueContainer(0));
34+
}
35+
else
36+
{
37+
throw new ExpressionEngineException(
38+
$"{parameters[0].GetValue<string>()} cannot be converted to float.");
39+
}
40+
41+
case ValueType.Integer:
42+
return new ValueTask<ValueContainer>(new ValueContainer((float)parameters[0].GetValue<int>()));
43+
44+
case ValueType.Float:
45+
return new ValueTask<ValueContainer>(new ValueContainer(parameters[0].GetValue<double>()));
46+
47+
case ValueType.Boolean:
48+
return new ValueTask<ValueContainer>(new ValueContainer((double)(parameters[0].GetValue<bool>() ? 0 : 1)));
49+
50+
default:
51+
throw new ExpressionEngineException(
52+
$"Float function can not operate on type: {parameters[0].Type()}.");
53+
}
54+
}
55+
}
56+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using ExpressionEngine.Functions.Base;
4+
using ExpressionEngine.Functions.CustomException;
5+
6+
namespace ExpressionEngine.Functions.Implementations.ConversionFunctions
7+
{
8+
public class IntFunction : Function
9+
{
10+
public IntFunction() : base("int")
11+
{
12+
}
13+
14+
public override ValueTask<ValueContainer> ExecuteFunction(params ValueContainer[] parameters)
15+
{
16+
if (parameters.Length != 1)
17+
{
18+
throw new ArgumentError(parameters.Length > 1 ? "Too many arguments" : "Too few arguments");
19+
}
20+
21+
switch (parameters[0].Type())
22+
{
23+
case ValueType.String:
24+
if (Int32.TryParse(parameters[0].GetValue<string>(), out int intValue))
25+
{
26+
CheckIntMaxOrMin(intValue);
27+
return new ValueTask<ValueContainer>(new ValueContainer(intValue));
28+
}
29+
else if (Double.TryParse(parameters[0].GetValue<string>(), out double doubleValue))
30+
{
31+
var intVal = (int)System.Math.Round(doubleValue);
32+
CheckIntMaxOrMin(intVal);
33+
return new ValueTask<ValueContainer>(new ValueContainer(intVal));
34+
}
35+
else if (Boolean.TryParse(parameters[0].GetValue<string>(), out bool boolVal))
36+
{
37+
if (boolVal)
38+
return new ValueTask<ValueContainer>(new ValueContainer(1));
39+
else
40+
return new ValueTask<ValueContainer>(new ValueContainer(0));
41+
}
42+
else
43+
{
44+
throw new ExpressionEngineException(
45+
$"{parameters[0].GetValue<string>()} cannot be converted to integer.");
46+
}
47+
48+
case ValueType.Integer:
49+
var val = parameters[0].GetValue<int>();
50+
CheckIntMaxOrMin(val);
51+
return new ValueTask<ValueContainer>(new ValueContainer(parameters[0].GetValue<int>()));
52+
53+
case ValueType.Float:
54+
var floatToIntVal = (int)System.Math.Round(parameters[0].GetValue<double>());
55+
CheckIntMaxOrMin(floatToIntVal);
56+
return new ValueTask<ValueContainer>(new ValueContainer((int)System.Math.Round(parameters[0].GetValue<double>())));
57+
58+
case ValueType.Boolean:
59+
return new ValueTask<ValueContainer>(new ValueContainer(parameters[0].GetValue<bool>() ? 1 : 0));
60+
61+
default:
62+
throw new ExpressionEngineException(
63+
$"Int function can not operate on type: {parameters[0].Type()}.");
64+
}
65+
}
66+
67+
private void CheckIntMaxOrMin(int val)
68+
{
69+
if (val == int.MinValue)
70+
throw new ExpressionEngineException(
71+
$"Input is less than minimum value of int {int.MinValue}");
72+
else if (val == int.MaxValue)
73+
throw new ExpressionEngineException(
74+
$"Input is greater than maximum value of int: {int.MaxValue}");
75+
}
76+
}
77+
}

ExpressionEngine/Functions/Implementations/StringFunctions/ConcatFunction.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,30 @@ public ConcatFunction() : base("concat")
1111
{
1212
}
1313

14+
/// <functionName>concat</functionName>
15+
/// <summary>
16+
/// Combine two or more strings, and return the combined string.
17+
/// </summary>
18+
/// <definition>
19+
/// concat('$lttext1$gt', '$lttext2$gt', ...)
20+
/// </definition>
21+
/// <parameters>
22+
/// <parameter def="$lttext1$gt, $lttext2$gt, ..." required="Yes" type="String">At least two strings to combine</parameter>
23+
/// </parameters>
24+
/// <returns>
25+
/// <value>$lttext1$gt, $lttext2$gt, ...</value>
26+
/// <type>String</type>
27+
/// <description>The string created from the combined input strings. <br/><br/> Note: The length of the result must not exceed 104,857,600 characters.</description>
28+
/// </returns>
1429
public override ValueTask<ValueContainer> ExecuteFunction(params ValueContainer[] parameters)
1530
{
1631
if (parameters.Length < 2)
1732
{
1833
throw new ArgumentError("Too few arguments");
1934
}
2035

21-
return new ValueTask<ValueContainer>(new ValueContainer(parameters.Aggregate("", (current, value) => current + AuxiliaryMethods.VcIsString(value))));
36+
return new ValueTask<ValueContainer>(new ValueContainer(parameters.Aggregate("",
37+
(current, value) => current + AuxiliaryMethods.VcIsString(value))));
2238
}
2339
}
2440
}

0 commit comments

Comments
 (0)