Skip to content

Commit

Permalink
Add NoInferredDivision option
Browse files Browse the repository at this point in the history
  • Loading branch information
Muximize committed Feb 24, 2024
1 parent 21a73a9 commit 403658a
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 10 deletions.
31 changes: 22 additions & 9 deletions CodeGen/Generators/QuantityRelationsParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,16 @@ internal static class QuantityRelationsParser
///
/// The format of a relation definition is "Quantity.Unit operator Quantity.Unit = Quantity.Unit" (See examples below).
/// "double" can be used as a unitless operand.
/// "1" can be used as the left operand to define inverse relations.
/// "1" can be used as the result operand to define inverse relations.
///
/// Division relations are inferred from multiplication relations,
/// but this can be skipped if the string ends with "NoInferredDivision".
/// </summary>
/// <example>
/// [
/// "Power.Watt = ElectricPotential.Volt * ElectricCurrent.Ampere",
/// "Speed.MeterPerSecond = Length.Meter / Duration.Second",
/// "ReciprocalLength.InverseMeter = 1 / Length.Meter"
/// "1 = Length.Meter * ReciprocalLength.InverseMeter"
/// "Power.Watt = ElectricPotential.Volt * ElectricCurrent.Ampere",
/// "Mass.Kilogram = MassConcentration.KilogramPerCubicMeter * Volume.CubicMeter -- NoInferredDivision",
/// ]
/// </example>
/// <param name="rootDir">Repository root directory.</param>
Expand Down Expand Up @@ -61,7 +64,7 @@ public static void ParseAndApplyRelations(string rootDir, Quantity[] quantities)

// We can infer division relations from multiplication relations.
relations.AddRange(relations
.Where(r => r.Operator is "*")
.Where(r => r is { Operator: "*", NoInferredDivision: false })
.Select(r => r with
{
Operator = "/",
Expand All @@ -74,9 +77,6 @@ public static void ParseAndApplyRelations(string rootDir, Quantity[] quantities)
.Where(r => r.LeftQuantity != r.RightQuantity)
.ToList());

// Remove inferred relation "MassConcentration = Mass / Volume" because it duplicates "Density = Mass / Volume"
relations.RemoveAll(r => r is { Operator: "/", ResultQuantity.Name: "MassConcentration", LeftQuantity.Name: "Mass", RightQuantity.Name: "Volume" });

// We can infer TimeSpan relations from Duration relations.
var timeSpanQuantity = pseudoQuantity with { Name = "TimeSpan" };
relations.AddRange(relations
Expand All @@ -103,6 +103,18 @@ public static void ParseAndApplyRelations(string rootDir, Quantity[] quantities)
throw new UnitsNetCodeGenException($"Duplicate inferred relations:\n {list}");
}

var ambiguous = relations
.GroupBy(r => $"{r.LeftQuantity.Name} {r.Operator} {r.RightQuantity.Name}")
.Where(g => g.Count() > 1)
.Select(g => g.Key)
.ToList();

if (ambiguous.Any())
{
var list = string.Join("\n ", ambiguous);
throw new UnitsNetCodeGenException($"Ambiguous inferred relations:\n {list}\n\nHint: you could use NoInferredDivision in the definition file.");
}

foreach (var quantity in quantities)
{
var quantityRelations = new List<QuantityRelation>();
Expand Down Expand Up @@ -151,7 +163,7 @@ private static QuantityRelation ParseRelation(string relationString, IReadOnlyDi
{
var segments = relationString.Split(' ');

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

return new QuantityRelation
{
NoInferredDivision = segments.Contains("NoInferredDivision"),
Operator = @operator,
LeftQuantity = leftQuantity,
LeftUnit = leftUnit,
Expand Down
1 change: 1 addition & 0 deletions CodeGen/JsonTypes/QuantityRelation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace CodeGen.JsonTypes
{
internal record QuantityRelation : IComparable<QuantityRelation>
{
public bool NoInferredDivision = false;
public string Operator = null!;

public Quantity LeftQuantity = null!;
Expand Down
2 changes: 1 addition & 1 deletion Common/UnitRelations.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"Mass.Kilogram = AreaDensity.KilogramPerSquareMeter * Area.SquareMeter",
"Mass.Kilogram = Density.KilogramPerCubicMeter * Volume.CubicMeter",
"Mass.Kilogram = LinearDensity.KilogramPerMeter * Length.Meter",
"Mass.Kilogram = MassConcentration.KilogramPerCubicMeter * Volume.CubicMeter",
"Mass.Kilogram = MassConcentration.KilogramPerCubicMeter * Volume.CubicMeter -- NoInferredDivision",
"Mass.Kilogram = MassFlow.KilogramPerSecond * Duration.Second",
"Mass.Kilogram = MassFraction.DecimalFraction * Mass.Kilogram",
"MassConcentration.KilogramPerCubicMeter = Molarity.MolePerCubicMeter * MolarMass.KilogramPerMole",
Expand Down

0 comments on commit 403658a

Please sign in to comment.