Skip to content

Commit 41a364b

Browse files
authored
Merge pull request #30 from Cysharp/hadashiA/numeric
Add options to define arithmetic operators separately
2 parents 3deabf1 + 4670481 commit 41a364b

File tree

14 files changed

+707
-133
lines changed

14 files changed

+707
-133
lines changed

README.md

Lines changed: 69 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,25 @@ public readonly partial struct Hp { }
6060
// -- generates
6161
6262
[System.ComponentModel.TypeConverter(typeof(HpTypeConverter))]
63-
public readonly partial struct Hp : IEquatable<Hp> , IComparable<Hp>
63+
public readonly partial struct Hp
64+
: IEquatable<Hp>
65+
#if NET7_0_OR_GREATER
66+
, IEqualityOperators<Hp, Hp, bool>
67+
#endif
68+
, IComparable<Hp>
69+
#if NET7_0_OR_GREATER
70+
, IComparisonOperators<Hp, Hp, bool>
71+
#endif
72+
#if NET7_0_OR_GREATER
73+
, IAdditionOperators<Hp, Hp, Hp>
74+
, ISubtractionOperators<Hp, Hp, Hp>
75+
, IMultiplyOperators<Hp, Hp, Hp>
76+
, IDivisionOperators<Hp, Hp, Hp>
77+
, IUnaryPlusOperators<Hp, Hp>
78+
, IUnaryNegationOperators<Hp, Hp>
79+
, IIncrementOperators<Hp>
80+
, IDecrementOperators<Hp>
81+
#endif
6482
{
6583
readonly int value;
6684

@@ -81,25 +99,27 @@ public readonly partial struct Hp : IEquatable<Hp> , IComparable<Hp>
8199
private class HpTypeConverter : System.ComponentModel.TypeConverter { /* snip... */ }
82100

83101
// UnitGenerateOptions.ArithmeticOperator
84-
public static Hp operator +(in Hp x, in Hp y) => new Hp(checked((int)(x.value + y.value)));
85-
public static Hp operator -(in Hp x, in Hp y) => new Hp(checked((int)(x.value - y.value)));
86-
public static Hp operator *(in Hp x, in Hp y) => new Hp(checked((int)(x.value * y.value)));
87-
public static Hp operator /(in Hp x, in Hp y) => new Hp(checked((int)(x.value / y.value)));
102+
public static Hp operator +(Hp x, Hp y) => new Hp(checked((int)(x.value + y.value)));
103+
public static Hp operator -(Hp x, Hp y) => new Hp(checked((int)(x.value - y.value)));
104+
public static Hp operator *(Hp x, Hp y) => new Hp(checked((int)(x.value * y.value)));
105+
public static Hp operator /(Hp x, Hp y) => new Hp(checked((int)(x.value / y.value)));
106+
public static Hp operator ++(Hp x) => new Hp(checked((int)(x.value + 1)));
107+
public static Hp operator --(Hp x) => new Hp(checked((int)(x.value - 1)));
108+
public static Hp operator +(A value) => new((int)(+value.value));
109+
public static Hp operator -(A value) => new((int)(-value.value));
88110

89111
// UnitGenerateOptions.ValueArithmeticOperator
90-
public static Hp operator ++(in Hp x) => new Hp(checked((int)(x.value + 1)));
91-
public static Hp operator --(in Hp x) => new Hp(checked((int)(x.value - 1)));
92-
public static Hp operator +(in Hp x, in int y) => new Hp(checked((int)(x.value + y)));
93-
public static Hp operator -(in Hp x, in int y) => new Hp(checked((int)(x.value - y)));
94-
public static Hp operator *(in Hp x, in int y) => new Hp(checked((int)(x.value * y)));
95-
public static Hp operator /(in Hp x, in int y) => new Hp(checked((int)(x.value / y)));
112+
public static Hp operator +(Hp x, in int y) => new Hp(checked((int)(x.value + y)));
113+
public static Hp operator -(Hp x, in int y) => new Hp(checked((int)(x.value - y)));
114+
public static Hp operator *(Hp x, in int y) => new Hp(checked((int)(x.value * y)));
115+
public static Hp operator /(Hp x, in int y) => new Hp(checked((int)(x.value / y)));
96116

97117
// UnitGenerateOptions.Comparable
98118
public int CompareTo(Hp other) => value.CompareTo(other.value);
99-
public static bool operator >(in Hp x, in Hp y) => x.value > y.value;
100-
public static bool operator <(in Hp x, in Hp y) => x.value < y.value;
101-
public static bool operator >=(in Hp x, in Hp y) => x.value >= y.value;
102-
public static bool operator <=(in Hp x, in Hp y) => x.value <= y.value;
119+
public static bool operator >(Hp x, Hp y) => x.value > y.value;
120+
public static bool operator <(Hp x, Hp y) => x.value < y.value;
121+
public static bool operator >=(Hp x, Hp y) => x.value >= y.value;
122+
public static bool operator <=(Hp x, Hp y) => x.value <= y.value;
103123

104124
// UnitGenerateOptions.MinMaxMethod
105125
public static Hp Min(Hp x, Hp y) => new Hp(Math.Min(x.value, y.value));
@@ -193,7 +213,12 @@ namespace UnitGenerator
193213
[AttributeUsage(AttributeTargets.Struct, AllowMultiple = false)]
194214
internal class UnitOfAttribute : Attribute
195215
{
196-
public UnitOfAttribute(Type type, UnitGenerateOptions options = UnitGenerateOptions.None, string toStringFormat = null)
216+
public Type Type { get; }
217+
public UnitGenerateOptions Options { get; }
218+
public UnitArithmeticOperators ArithmeticOperators { get; set; }
219+
public string ToStringFormat { get; set; }
220+
221+
public UnitOfAttribute(Type type, UnitGenerateOptions options = UnitGenerateOptions.None) { ... }
197222
}
198223
}
199224
```
@@ -241,7 +266,9 @@ public static GroupId NewGroupId();
241266

242267
Second parameter `UnitGenerateOptions options` can configure which method to implement, default is `None`.
243268

244-
Third parameter `strign toStringFormat` can configure `ToString` format. Default is null and output as $`{0}`.
269+
Optional named parameter: `ArithmeticOperators` can configure which generates operators specifically. Default is `Number`. (This can be used if UnitGenerateOptions.ArithmeticOperator is specified.)
270+
271+
Optional named parameter: `ToStringFormat` can configure `ToString` format. Default is null and output as $`{0}`.
245272

246273
## UnitGenerateOptions
247274

@@ -324,13 +351,36 @@ public static T operator +(in T x, in T y) => new T(checked((U)(x.value + y.valu
324351
public static T operator -(in T x, in T y) => new T(checked((U)(x.value - y.value)));
325352
public static T operator *(in T x, in T y) => new T(checked((U)(x.value * y.value)));
326353
public static T operator /(in T x, in T y) => new T(checked((U)(x.value / y.value)));
354+
public static T operator +(T value) => new((U)(+value.value));
355+
public static T operator -(T value) => new((U)(-value.value));
356+
public static T operator ++(T x) => new T(checked((U)(x.value + 1)));
357+
public static T operator --(T x) => new T(checked((U)(x.value - 1)));
358+
```
359+
360+
In addition, all members conforming to [System.Numerics.INumber<T>](https://learn.microsoft.com/ja-jp/dotnet/api/system.numerics.inumber-1) are generated.
361+
362+
If you want to suppress this and generate only certain operators, you can use the the `ArithmeticOperatros` option of `[UnitOf]` attribute as follows:
363+
364+
```csharp
365+
[UnitOf(
366+
typeof(int),
367+
UnitGenerateOptions.ArithmeticOperator,
368+
ArithmeticOperators = UnitArithmeticOperators.Addition | UnitArithmeticOperators.Subtraction)]
369+
public readonly partial struct Hp { }
327370
```
328371

372+
| Value | Generates |
373+
|-------------------------------------|----------------------------------------------------------------------------------------|
374+
| UnitArithmeticOperators.Addition | `T operator +(T, T)` |
375+
| UnitArithmeticOperators.Subtraction | `T operator -(T, T)` |
376+
| UnitArithmeticOperators.Multiply | `T operator *(T, T)`, `T operator +(T)`, `T operator-(T)` |
377+
| UnitArithmeticOperators.Division | `T operator /(T, T)`, `T operator +(T)`, `T operator-(T)` |
378+
| UnitArithmeticOperators.Increment | `T operator ++(T)` |
379+
| UnitArithmeticOperators.Decrement | `T operator --(T)` |
380+
329381
### ValueArithmeticOperator
330382

331383
```csharp
332-
public static T operator ++(in T x) => new T(checked((U)(x.value + 1)));
333-
public static T operator --(in T x) => new T(checked((U)(x.value - 1)));
334384
public static T operator +(in T x, in U y) => new T(checked((U)(x.value + y)));
335385
public static T operator -(in T x, in U y) => new T(checked((U)(x.value - y)));
336386
public static T operator *(in T x, in U y) => new T(checked((U)(x.value * y)));

sandbox/ConsoleApp/AllPrimitives.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Globalization;
34
using System.Linq;
5+
using System.Numerics;
46
using System.Text;
57
using System.Text.Json;
68
using System.Text.Json.Serialization;

sandbox/ConsoleApp/ConsoleApp.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFramework>net6.0</TargetFramework>
5+
<TargetFramework>net7.0</TargetFramework>
66
<Nullable>enable</Nullable>
77
<IsPackable>false</IsPackable>
88
</PropertyGroup>

sandbox/ConsoleApp/Operators.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using UnitGenerator;
2+
3+
namespace ConsoleApp
4+
{
5+
namespace ConsoleApp
6+
{
7+
[UnitOf(typeof(int), UnitGenerateOptions.ArithmeticOperator | UnitGenerateOptions.ValueArithmeticOperator, ArithmeticOperators = UnitArithmeticOperators.Addition)]
8+
public readonly partial struct Add
9+
{
10+
}
11+
12+
[UnitOf(typeof(int), UnitGenerateOptions.ArithmeticOperator | UnitGenerateOptions.ValueArithmeticOperator, ArithmeticOperators = UnitArithmeticOperators.Subtraction)]
13+
public readonly partial struct Sub
14+
{
15+
}
16+
17+
[UnitOf(typeof(int), UnitGenerateOptions.ArithmeticOperator | UnitGenerateOptions.ValueArithmeticOperator, ArithmeticOperators = UnitArithmeticOperators.Multiply)]
18+
public readonly partial struct Mul
19+
{
20+
}
21+
22+
[UnitOf(typeof(int), UnitGenerateOptions.ArithmeticOperator | UnitGenerateOptions.ValueArithmeticOperator, ArithmeticOperators = UnitArithmeticOperators.Division)]
23+
public readonly partial struct Div
24+
{
25+
}
26+
27+
[UnitOf(typeof(int), UnitGenerateOptions.ArithmeticOperator | UnitGenerateOptions.ValueArithmeticOperator, ArithmeticOperators = UnitArithmeticOperators.Increment)]
28+
public readonly partial struct Inc
29+
{
30+
}
31+
32+
[UnitOf(typeof(int), UnitGenerateOptions.ArithmeticOperator | UnitGenerateOptions.ValueArithmeticOperator, ArithmeticOperators = UnitArithmeticOperators.Decrement)]
33+
public readonly partial struct Dec
34+
{
35+
}
36+
}
37+
}

sandbox/ConsoleApp/Program.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@ public readonly partial struct BarId { }
3535

3636
namespace Sample
3737
{
38-
39-
[UnitOf(typeof(int), UnitGenerateOptions.ArithmeticOperator | UnitGenerateOptions.ValueArithmeticOperator | UnitGenerateOptions.Comparable | UnitGenerateOptions.MinMaxMethod | UnitGenerateOptions.JsonConverter | UnitGenerateOptions.JsonConverterDictionaryKeySupport)]
38+
[UnitOf(typeof(int), UnitGenerateOptions.ArithmeticOperator | UnitGenerateOptions.Comparable | UnitGenerateOptions.MinMaxMethod | UnitGenerateOptions.JsonConverter | UnitGenerateOptions.JsonConverterDictionaryKeySupport)]
4039
public readonly partial struct Hp
4140
{
4241
// public static Hp operator +(in Hp x, in Hp y) => new Hp(checked((int)(x.value + y.value)));
@@ -83,7 +82,7 @@ public void Foo()
8382
_ = AsPrimitive();
8483
}
8584
}
86-
85+
8786
[UnitOf(typeof(string), UnitGenerateOptions.ParseMethod)]
8887
public readonly partial struct StringId { }
8988
}

sandbox/FileGenerate/FileGenerate.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net6.0</TargetFramework>
4+
<TargetFramework>net7.0</TargetFramework>
55

66
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
77
<CompilerGeneratedFilesOutputPath>$(ProjectDir)..\Generated</CompilerGeneratedFilesOutputPath>
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Text;
5-
using System.Threading.Tasks;
6-
using UnitGenerator;
1+
using UnitGenerator;
72

83
namespace FileGenerate
94
{
@@ -16,4 +11,9 @@ public readonly partial struct A
1611
public readonly partial struct B
1712
{
1813
}
14+
15+
[UnitOf(typeof(int), UnitGenerateOptions.Comparable | UnitGenerateOptions.ArithmeticOperator | UnitGenerateOptions.ValueArithmeticOperator)]
16+
public readonly partial struct C
17+
{
18+
}
1919
}

sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.A.Generated.cs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,18 @@
33
// </auto-generated>
44
#pragma warning disable CS8669
55
using System;
6+
using System.Globalization;
7+
#if NET7_0_OR_GREATER
8+
using System.Numerics;
9+
#endif
610
namespace FileGenerate
711
{
812
[System.ComponentModel.TypeConverter(typeof(ATypeConverter))]
9-
readonly partial struct A : IEquatable<A>
13+
readonly partial struct A
14+
: IEquatable<A>
15+
#if NET7_0_OR_GREATER
16+
, IEqualityOperators<A, A, bool>
17+
#endif
1018
{
1119
readonly int value;
1220

@@ -47,28 +55,29 @@ public override bool Equals(object obj)
4755

4856
return value.Equals(obj);
4957
}
50-
51-
public override int GetHashCode()
58+
59+
public static bool operator ==(A x, A y)
5260
{
53-
return value.GetHashCode();
61+
return x.value.Equals(y.value);
5462
}
5563

56-
public override string ToString()
64+
public static bool operator !=(A x, A y)
5765
{
58-
return value.ToString();
66+
return !x.value.Equals(y.value);
5967
}
6068

61-
public static bool operator ==(in A x, in A y)
69+
public override int GetHashCode()
6270
{
63-
return x.value.Equals(y.value);
71+
return value.GetHashCode();
6472
}
6573

66-
public static bool operator !=(in A x, in A y)
74+
public override string ToString()
6775
{
68-
return !x.value.Equals(y.value);
76+
return value.ToString();
6977
}
7078

7179
// Default
80+
7281
private class ATypeConverter : System.ComponentModel.TypeConverter
7382
{
7483
private static readonly Type WrapperType = typeof(A);

sandbox/Generated/UnitGenerator/UnitGenerator.SourceGenerator/FileGenerate.B.Generated.cs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,18 @@
33
// </auto-generated>
44
#pragma warning disable CS8669
55
using System;
6+
using System.Globalization;
7+
#if NET7_0_OR_GREATER
8+
using System.Numerics;
9+
#endif
610
namespace FileGenerate
711
{
812
[System.ComponentModel.TypeConverter(typeof(BTypeConverter))]
9-
readonly partial struct B : IEquatable<B>
13+
readonly partial struct B
14+
: IEquatable<B>
15+
#if NET7_0_OR_GREATER
16+
, IEqualityOperators<B, B, bool>
17+
#endif
1018
{
1119
readonly string value;
1220

@@ -47,28 +55,29 @@ public override bool Equals(object obj)
4755

4856
return value.Equals(obj);
4957
}
50-
51-
public override int GetHashCode()
58+
59+
public static bool operator ==(B x, B y)
5260
{
53-
return value.GetHashCode();
61+
return x.value.Equals(y.value);
5462
}
5563

56-
public override string ToString()
64+
public static bool operator !=(B x, B y)
5765
{
58-
return value.ToString();
66+
return !x.value.Equals(y.value);
5967
}
6068

61-
public static bool operator ==(in B x, in B y)
69+
public override int GetHashCode()
6270
{
63-
return x.value.Equals(y.value);
71+
return value.GetHashCode();
6472
}
6573

66-
public static bool operator !=(in B x, in B y)
74+
public override string ToString()
6775
{
68-
return !x.value.Equals(y.value);
76+
return value.ToString();
6977
}
7078

7179
// Default
80+
7281
private class BTypeConverter : System.ComponentModel.TypeConverter
7382
{
7483
private static readonly Type WrapperType = typeof(B);

0 commit comments

Comments
 (0)