3 ms·
I am not an Ada expert, but I came up with this. Please notice that the idea here is not to have the compiler do proper dimensional analysis but simply to avoi
by tmcb 6y ago
I am not an Ada expert, but I came up with this. Please notice that the idea here is not to have the compiler do proper dimensional analysis but simply to avoid the default operator overloading of "*" for the Distance type that also returns a Distance value.
Nothing very high-level, as we need to explicitly manipulate the single-component records, but it does the job.
with Ada.Text_IO; use Ada.Text_IO;
procedure Main is
type Distance is record
Value : Float;
end record;
type Area is record
Value : Float;
end record;
function "*" (Left, Right : Distance) return Area is
begin
return (Value => Left.Value * Right.Value);
end "*";
D1 : constant Distance := (Value => 10.0);
D2 : constant Distance := (Value => 20.0);
-- D3 : constant Distance := D1 * D2;
-- Does not compile. GNAT returns the following error:
-- main.adb:21:33: expected type "Distance" defined at line 4
-- main.adb:21:33: found type "Area" defined at line 8
A : constant Area := D1 * D2;
begin
Put_Line ("Area A is " & Float'Image(A.Value));
end Main;*
- ajdude 6y agoThis is the right way to approach it on my opinion.
- yannickmoy 6y agoAs someone said, the best solution here is to use the dimensionality analysis in GNAT: https://docs.adacore.com/gnat_ugn-docs/html/gnat_ugn/gnat_ugn/gnat_and_program_execution.html#performing-dimensionality-analysis-in-gnat https://docs.adacore.com/gnat_ugn-docs/html/gnat_ugn/gnat_ug... as in: with Ada.Text_IO; use Ada.Text_IO; with System.Dim.Float_Mks; use System.Dim.Float_Mks; with System.Dim.Float_Mks_IO; use System.Dim.Float_Mks_IO; procedure Main is subtype Distance is System.Dim.Float_Mks.Length; subtype Area is System.Dim.Float_Mks.Area; D1 : constant Distance := 10.0*m; D2 : constant Distance := 20.0*m; -- D3 : constant Distance := D1 * D2; -- Does not compile. GNAT returns the following error: -- main.adb:13:08: dimensions mismatch in object declaration -- main.adb:13:37: expected dimension [L], found [L**2] A : constant Area := D1 * D2; begin -- print: Area A is 2.00000E+02 m**2 Put ("Area A is "); Put (Item => A); Put_Line (""); end Main;
- tmcb 6y agoOh, thanks for pointing it out. Honestly, I was more interested in leveraging the type system than on proper dimensional analysis. I could find no mechanism by which Ada allows the programmer to disable the default operation overloads, so I decided to try that out.
- OneWingedShark 6y agoIIRC you can disable/forbid the default like so: Function "*"(Left, Right: Distance) return Distance is abstract; then use: Function "*"(Left, Right : Distance) return Area;
- tmcb 6y agoThat seems to do the trick for an individual predefined operator specification. Thanks!