Skip to content

Commit 403658a

Browse files
committed
Add NoInferredDivision option
1 parent 21a73a9 commit 403658a

File tree

3 files changed

+24
-10
lines changed

3 files changed

+24
-10
lines changed

CodeGen/Generators/QuantityRelationsParser.cs

Lines changed: 22 additions & 9 deletions
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 = "/",
@@ -74,9 +77,6 @@ public static void ParseAndApplyRelations(string rootDir, Quantity[] quantities)
7477
.Where(r => r.LeftQuantity != r.RightQuantity)
7578
.ToList());
7679

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" });
79-
8080
// We can infer TimeSpan relations from Duration relations.
8181
var timeSpanQuantity = pseudoQuantity with { Name = "TimeSpan" };
8282
relations.AddRange(relations
@@ -103,6 +103,18 @@ public static void ParseAndApplyRelations(string rootDir, Quantity[] quantities)
103103
throw new UnitsNetCodeGenException($"Duplicate inferred relations:\n {list}");
104104
}
105105

106+
var ambiguous = relations
107+
.GroupBy(r => $"{r.LeftQuantity.Name} {r.Operator} {r.RightQuantity.Name}")
108+
.Where(g => g.Count() > 1)
109+
.Select(g => g.Key)
110+
.ToList();
111+
112+
if (ambiguous.Any())
113+
{
114+
var list = string.Join("\n ", ambiguous);
115+
throw new UnitsNetCodeGenException($"Ambiguous inferred relations:\n {list}\n\nHint: you could use NoInferredDivision in the definition file.");
116+
}
117+
106118
foreach (var quantity in quantities)
107119
{
108120
var quantityRelations = new List<QuantityRelation>();
@@ -151,7 +163,7 @@ private static QuantityRelation ParseRelation(string relationString, IReadOnlyDi
151163
{
152164
var segments = relationString.Split(' ');
153165

154-
if (segments is not [_, "=", _, "*", _])
166+
if (segments is not [_, "=", _, "*", _, ..])
155167
{
156168
throw new Exception($"Invalid relation string: {relationString}");
157169
}
@@ -176,6 +188,7 @@ private static QuantityRelation ParseRelation(string relationString, IReadOnlyDi
176188

177189
return new QuantityRelation
178190
{
191+
NoInferredDivision = segments.Contains("NoInferredDivision"),
179192
Operator = @operator,
180193
LeftQuantity = leftQuantity,
181194
LeftUnit = leftUnit,

CodeGen/JsonTypes/QuantityRelation.cs

Lines changed: 1 addition & 0 deletions
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

Lines changed: 1 addition & 1 deletion
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)