Skip to content

Commit c4ebb8c

Browse files
committed
Add NoInferredDivision option
1 parent 0fe25aa commit c4ebb8c

File tree

3 files changed

+24
-10
lines changed

3 files changed

+24
-10
lines changed

CodeGen/Generators/QuantityRelationsParser.cs

+22-9
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,16 @@ internal static class QuantityRelationsParser
2525
///
2626
/// The format of a relation definition is "Quantity.Unit operator Quantity.Unit = Quantity.Unit" (See examples below).
2727
/// "double" can be used as a unitless operand.
28-
/// "1" can be used as the left operand to define inverse relations.
28+
/// "1" can be used as the result operand to define inverse relations.
29+
///
30+
/// Division relations are inferred from multiplication relations,
31+
/// but this can be skipped if the string ends with "NoInferredDivision".
2932
/// </summary>
3033
/// <example>
3134
/// [
32-
/// "Power.Watt = ElectricPotential.Volt * ElectricCurrent.Ampere",
33-
/// "Speed.MeterPerSecond = Length.Meter / Duration.Second",
34-
/// "ReciprocalLength.InverseMeter = 1 / Length.Meter"
35+
/// "1 = Length.Meter * ReciprocalLength.InverseMeter"
36+
/// "Power.Watt = ElectricPotential.Volt * ElectricCurrent.Ampere",
37+
/// "Mass.Kilogram = MassConcentration.KilogramPerCubicMeter * Volume.CubicMeter -- NoInferredDivision",
3538
/// ]
3639
/// </example>
3740
/// <param name="rootDir">Repository root directory.</param>
@@ -61,7 +64,7 @@ public static void ParseAndApplyRelations(string rootDir, Quantity[] quantities)
6164

6265
// We can infer division relations from multiplication relations.
6366
relations.AddRange(relations
64-
.Where(r => r.Operator is "*")
67+
.Where(r => r is { Operator: "*", NoInferredDivision: false })
6568
.Select(r => r with
6669
{
6770
Operator = "/",
@@ -73,9 +76,6 @@ public static void ParseAndApplyRelations(string rootDir, Quantity[] quantities)
7376
// Skip division between equal quantities because the ratio is already generated as part of the Arithmetic Operators.
7477
.Where(r => r.LeftQuantity != r.RightQuantity)
7578
.ToList());
76-
77-
// Remove inferred relation "MassConcentration = Mass / Volume" because it duplicates "Density = Mass / Volume"
78-
relations.RemoveAll(r => r is { Operator: "/", ResultQuantity.Name: "MassConcentration", LeftQuantity.Name: "Mass", RightQuantity.Name: "Volume" });
7979

8080
// Sort all relations to keep generated operators in a consistent order.
8181
relations.Sort();
@@ -91,6 +91,18 @@ public static void ParseAndApplyRelations(string rootDir, Quantity[] quantities)
9191
var list = string.Join("\n ", duplicates);
9292
throw new UnitsNetCodeGenException($"Duplicate inferred relations:\n {list}");
9393
}
94+
95+
var ambiguous = relations
96+
.GroupBy(r => $"{r.LeftQuantity.Name} {r.Operator} {r.RightQuantity.Name}")
97+
.Where(g => g.Count() > 1)
98+
.Select(g => g.Key)
99+
.ToList();
100+
101+
if (ambiguous.Any())
102+
{
103+
var list = string.Join("\n ", ambiguous);
104+
throw new UnitsNetCodeGenException($"Ambiguous inferred relations:\n {list}\n\nHint: you could use NoInferredDivision in the definition file.");
105+
}
94106

95107
foreach (var quantity in quantities)
96108
{
@@ -140,7 +152,7 @@ private static QuantityRelation ParseRelation(string relationString, IReadOnlyDi
140152
{
141153
var segments = relationString.Split(' ');
142154

143-
if (segments is not [_, "=", _, "*", _])
155+
if (segments is not [_, "=", _, "*", _, ..])
144156
{
145157
throw new Exception($"Invalid relation string: {relationString}");
146158
}
@@ -165,6 +177,7 @@ private static QuantityRelation ParseRelation(string relationString, IReadOnlyDi
165177

166178
return new QuantityRelation
167179
{
180+
NoInferredDivision = segments.Contains("NoInferredDivision"),
168181
Operator = @operator,
169182
LeftQuantity = leftQuantity,
170183
LeftUnit = leftUnit,

CodeGen/JsonTypes/QuantityRelation.cs

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ namespace CodeGen.JsonTypes
77
{
88
internal record QuantityRelation : IComparable<QuantityRelation>
99
{
10+
public bool NoInferredDivision = false;
1011
public string Operator = null!;
1112

1213
public Quantity LeftQuantity = null!;

Common/UnitRelations.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"Mass.Kilogram = AreaDensity.KilogramPerSquareMeter * Area.SquareMeter",
3838
"Mass.Kilogram = Density.KilogramPerCubicMeter * Volume.CubicMeter",
3939
"Mass.Kilogram = LinearDensity.KilogramPerMeter * Length.Meter",
40-
"Mass.Kilogram = MassConcentration.KilogramPerCubicMeter * Volume.CubicMeter",
40+
"Mass.Kilogram = MassConcentration.KilogramPerCubicMeter * Volume.CubicMeter -- NoInferredDivision",
4141
"Mass.Kilogram = MassFlow.KilogramPerSecond * Duration.Second",
4242
"Mass.Kilogram = MassFraction.DecimalFraction * Mass.Kilogram",
4343
"MassConcentration.KilogramPerCubicMeter = Molarity.MolePerCubicMeter * MolarMass.KilogramPerMole",

0 commit comments

Comments
 (0)