Search code examples
adagnat

Unexpected Ada Type Compatibility


Why are Volts, Amps, and Ohms compatible?


with ada.text_io; use ada.text_io;
                                                                    
procedure main is                                                   
    type Volts is delta 1.0 / 2.0 ** 12 range -45_000.0 .. 45_000.0;
    type Amps is delta 1.0 / 2.0 ** 16 range -1_000.0 .. 1_000.0;   
    type Ohms is delta 0.125 range 0.0 .. 1.0E8;                    
                                                                    
    V : Volts := 1.0;                                               
    A : Amps := 1.0;                                                
    R1 : Ohms := 1.0;                                               
    R2 : Ohms := 1.0;                                               
                                                                   
begin                                             
                     
    v := A * (R1 + R2);
                       
    put_line(V'Img);   
                       
end main;  

If the types the types are defined as new Float I get the following exception during compilation:


main.adb:22:12: error: invalid operand types for operator "*"
main.adb:22:12: error: left operand has type "Amps" defined at line 5
main.adb:22:12: error: right operand has type "Ohms" defined at line 6

I expected the use of type with Volts to define a new type that was incompatible with the other types as it wasn't an explicit subtype of the fixed point type.


Solution

  • Multiplication and division with operands of different fixed-point types is explicitly allowed (predefined) in the Ada standard since Ada 95 -- see http://www.ada-auth.org/standards/22rm/html/RM-4-5-5.html, paragraph 18 -- but only in a context where the result is also expected to be of some fixed-point type (see paragraph 19.1/2). Addition and subtraction between different fixed-point types is not predefined, and of course different fixed-point types are not compatible in eg. parameters or assignment.

    As to why * and / are allowed between different types, I don't have a clear answer. One of the relevant Ada Issues (http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ais/ai-00364.txt?rev=1.15) has this brief comment by Randy Brukardt: "... the Ada 95 rules came about because people complained about having to write a type conversion in: A := B * 5.0; which was felt to make Ada look bad.".

    The same AI also has comments critical of the new rule... so opinions differ.