Skip to content

Commit da623f9

Browse files
committed
Make early exits produce expressions
1 parent 5effd82 commit da623f9

34 files changed

Lines changed: 366 additions & 20 deletions

Src/FastData.Generator.CPlusPlus/Internal/Framework/CPlusPlusEarlyExitDef.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Genbox.FastData.Generator.Framework.Definitions;
66
using Genbox.FastData.Generator.Helpers;
77
using Genbox.FastData.Generators.EarlyExits;
8+
using static Genbox.FastData.Generators.Helpers.TypeHelper;
89

910
namespace Genbox.FastData.Generator.CPlusPlus.Internal.Framework;
1011

@@ -51,9 +52,9 @@ protected override string GetValueEarlyExit<T>(MethodType methodType, T min, T m
5152

5253
protected override string GetValueBitMaskEarlyExit<T>(MethodType methodType, ulong mask)
5354
{
54-
Type unsignedType = TypeHelper.GetUnsignedType(typeof(T));
55+
Type unsignedType = GetUnsignedType(typeof(T));
5556
string unsignedTypeName = map.GetTypeName(unsignedType);
56-
object maskValue = TypeHelper.ConvertValueToType(mask, unsignedType);
57+
object maskValue = ConvertValueToType(mask, unsignedType);
5758
string maskLiteral = map.ToValueLabel(maskValue, unsignedType);
5859

5960
return $"""

Src/FastData.Generator.CSharp.TestHarness/CSharpBootstrap.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Genbox.FastData.Enums;
2+
using Genbox.FastData.Generator.CSharp.Internal;
23
using Genbox.FastData.Generator.CSharp.Internal.Framework;
34
using Genbox.FastData.Generator.Framework;
45
using Genbox.FastData.Generators.Abstracts;
@@ -19,6 +20,8 @@ public CSharpBootstrap(HarnessType type) : base("CSharp", ".cs", type, "mcr.micr
1920

2021
public override ICodeGenerator Generator => CSharpCodeGenerator.Create(new CSharpCodeGeneratorConfig("FastData"));
2122

23+
public ExpressionCompiler CreateExpressionCompiler() => new CSharpExpressionCompiler(Map);
24+
2225
private static string GetCommandTemplate(HarnessType type) =>
2326
type == HarnessType.Test
2427
? "dotnet run -c Debug -p:DebugType=None -p:DebugSymbols=false {0}"

Src/FastData.Generator.CSharp/Internal/Framework/CSharpEarlyExitDef.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Genbox.FastData.Generator.Framework.Definitions;
66
using Genbox.FastData.Generator.Helpers;
77
using Genbox.FastData.Generators.EarlyExits;
8+
using Genbox.FastData.Generators.Helpers;
89
using static Genbox.FastData.Generator.CSharp.Internal.StringHelper;
910

1011
namespace Genbox.FastData.Generator.CSharp.Internal.Framework;

Src/FastData.Generator.Rust/Internal/Framework/RustEarlyExitDef.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Genbox.FastData.Generator.Helpers;
66
using Genbox.FastData.Generator.Rust.Enums;
77
using Genbox.FastData.Generators.EarlyExits;
8+
using Genbox.FastData.Generators.Helpers;
89

910
namespace Genbox.FastData.Generator.Rust.Internal.Framework;
1011

Src/FastData.Generator/ExpressionCompiler.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ protected override Expression VisitBinary(BinaryExpression node)
131131

132132
protected override Expression VisitConstant(ConstantExpression node)
133133
{
134+
if (node.Value is Enum && node.Type.IsEnum)
135+
{
136+
Output.Append(node.Type.Name).Append(".").Append(node.Value.ToString());
137+
return node;
138+
}
139+
134140
string str = node.Value switch
135141
{
136142
char x => map.ToValueLabel(x),
@@ -168,6 +174,13 @@ protected override Expression VisitUnary(UnaryExpression node)
168174
return node;
169175
}
170176

177+
if (node.NodeType == ExpressionType.Not)
178+
{
179+
Output.Append("!");
180+
Visit(node.Operand);
181+
return node;
182+
}
183+
171184
Visit(node.Operand);
172185
switch (node.NodeType)
173186
{
@@ -250,6 +263,14 @@ protected override Expression VisitGoto(GotoExpression node)
250263
ExpressionType.LeftShift => " << ",
251264
ExpressionType.RightShift => " >> ",
252265
ExpressionType.Or => " | ",
266+
ExpressionType.And => " & ",
267+
ExpressionType.AndAlso => " && ",
268+
ExpressionType.OrElse => " || ",
269+
ExpressionType.Modulo => " % ",
270+
ExpressionType.Equal => " == ",
271+
ExpressionType.NotEqual => " != ",
272+
ExpressionType.LessThan => " < ",
273+
ExpressionType.LessThanOrEqual => " <= ",
253274
ExpressionType.GreaterThan => " > ",
254275
ExpressionType.GreaterThanOrEqual => " >= ",
255276
ExpressionType.AddAssign => " += ",

Src/FastData.Generator/Framework/Definitions/EarlyExitDef.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public string GetEarlyExits<T>(IEnumerable<IEarlyExit> earlyExits, MethodType me
3838
sb.AppendLine(GetStringPrefixSuffixEarlyExit(methodType, prefix, suffix, ignoreCase));
3939
else if (spec is ValueRangeEarlyExit<T>(var minValue, var maxValue))
4040
sb.AppendLine(GetValueEarlyExit(methodType, minValue, maxValue));
41-
else if (spec is ValueBitMaskEarlyExit(var mask))
41+
else if (spec is ValueBitMaskEarlyExit<T>(var mask))
4242
sb.AppendLine(GetValueBitMaskEarlyExit<T>(methodType, mask));
4343
else
4444
throw new InvalidOperationException("Unknown early exit type: " + spec.GetType().Name);
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System.Linq.Expressions;
2+
using Genbox.FastData.Generator;
3+
using Genbox.FastData.Generators.Abstracts;
4+
using Genbox.FastData.TestHarness.Runner.Code.Theory;
5+
using static Genbox.FastData.TestHarness.Runner.Code.VerifyHelper;
6+
7+
namespace Genbox.FastData.TestHarness.Runner.Code.Abstracts;
8+
9+
public abstract class EarlyExitTestBase
10+
{
11+
protected abstract string HarnessName { get; }
12+
protected abstract ExpressionCompiler CreateCompiler();
13+
14+
[Theory]
15+
[ClassData(typeof(EarlyExitExpressions))]
16+
public Task EarlyExitExpression(EarlyExitVector vector) => VerifyAsync(vector);
17+
18+
private Task VerifyAsync(EarlyExitVector vector)
19+
{
20+
string source = Compile(vector.EarlyExit);
21+
string id = $"{nameof(EarlyExitExpressions)}_{vector.Id}";
22+
return VerifyEarlyExitAsync(HarnessName, id, source);
23+
}
24+
25+
private string Compile(IEarlyExit earlyExit)
26+
{
27+
Expression expression = earlyExit.GetExpression("key");
28+
ExpressionCompiler compiler = CreateCompiler();
29+
return compiler.GetCode(expression, 0);
30+
}
31+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using Genbox.FastData.Generators.Abstracts;
2+
using Genbox.FastData.Generators.EarlyExits;
3+
4+
namespace Genbox.FastData.TestHarness.Runner.Code.Theory;
5+
6+
public sealed record EarlyExitVector(string Id, IEarlyExit EarlyExit);
7+
8+
public sealed class EarlyExitExpressions : TheoryData<EarlyExitVector>
9+
{
10+
public EarlyExitExpressions()
11+
{
12+
Add(new EarlyExitVector(nameof(LengthEqualEarlyExit), new LengthEqualEarlyExit(4, 8)));
13+
Add(new EarlyExitVector(nameof(LengthRangeEarlyExit), new LengthRangeEarlyExit(2, 5, 4, 10)));
14+
Add(new EarlyExitVector(nameof(LengthBitmapEarlyExit), new LengthBitmapEarlyExit([10ul, 5ul])));
15+
Add(new EarlyExitVector(nameof(CharRangeEarlyExit), new CharRangeEarlyExit(CharPosition.First, 'a', 'z')));
16+
Add(new EarlyExitVector(nameof(CharEqualsEarlyExit), new CharEqualsEarlyExit(CharPosition.Last, 'x')));
17+
Add(new EarlyExitVector(nameof(CharBitmapEarlyExit), new CharBitmapEarlyExit(CharPosition.First, 1ul, 2ul)));
18+
Add(new EarlyExitVector(nameof(StringBitMaskEarlyExit), new StringBitMaskEarlyExit(65535ul, 4)));
19+
Add(new EarlyExitVector(nameof(StringPrefixSuffixEarlyExit), new StringPrefixSuffixEarlyExit("pre", "suf")));
20+
Add(new EarlyExitVector(nameof(ValueRangeEarlyExit<>), new ValueRangeEarlyExit<int>(10, 20)));
21+
Add(new EarlyExitVector(nameof(ValueBitMaskEarlyExit<>), new ValueBitMaskEarlyExit<ulong>(65280ul)));
22+
}
23+
}

Src/FastData.TestHarness.Runner/Code/VerifyHelper.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,10 @@ await Verify(source)
1313
.UseFileName(snapshotId)
1414
.UseDirectory("../Verify/Vectors/" + harnessName)
1515
.DisableDiff();
16+
17+
internal static async Task VerifyEarlyExitAsync(string harnessName, string snapshotId, string source) =>
18+
await Verify(source)
19+
.UseFileName(snapshotId)
20+
.UseDirectory("../Verify/EarlyExits/" + harnessName)
21+
.DisableDiff();
1622
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using Genbox.FastData.Generator.CSharp.TestHarness;
2+
using Genbox.FastData.Generator;
3+
using Genbox.FastData.InternalShared.Harness.Enums;
4+
using Genbox.FastData.TestHarness.Runner.Code.Abstracts;
5+
6+
namespace Genbox.FastData.TestHarness.Runner.Tests.CSharp;
7+
8+
public sealed class CSharpEarlyExitTests : EarlyExitTestBase
9+
{
10+
private static readonly CSharpBootstrap Bootstrap = new CSharpBootstrap(HarnessType.Test);
11+
12+
protected override string HarnessName => Bootstrap.Name;
13+
protected override ExpressionCompiler CreateCompiler() => Bootstrap.CreateExpressionCompiler();
14+
}

0 commit comments

Comments
 (0)