Redefining the 'Image attribute

In Ada 2022, you can redefine 'Image attribute for your type, though the syntax to do this has been changed several times. Let's see how it works in GNAT Community 2021.

Note

Redefining attribute 'Image is supported by

  • GNAT Community Edition 2021 (using Text_Buffers)

  • GNAT Community Edition 2020 (using Text_Output.Utils)

  • GCC 11 (using Text_Output.Utils)

In our example, let's redefine the 'Image attribute for a location in source code. To do this, we provide a new Put_Image aspect for the type:

    
    
    
        
pragma Ada_2022; with Ada.Text_IO; with Ada.Strings.Text_Buffers; procedure Main is type Source_Location is record Line : Positive; Column : Positive; end record with Put_Image => My_Put_Image; procedure My_Put_Image (Output : in out Ada.Strings.Text_Buffers.Root_Buffer_Type'Class; Value : Source_Location); procedure My_Put_Image (Output : in out Ada.Strings.Text_Buffers.Root_Buffer_Type'Class; Value : Source_Location) is Line : constant String := Value.Line'Image; Column : constant String := Value.Column'Image; Result : constant String := Line (2 .. Line'Last) & ':' & Column (2 .. Column'Last); begin Output.Put (Result); end My_Put_Image; Line_10 : constant Source_Location := (Line => 10, Column => 1); begin Ada.Text_IO.Put_Line (Line_10'Image); end Main;

What's the Root_Buffer_Type?

Let's see how it's defined in the Ada.Strings.Text_Buffers package.

type Root_Buffer_Type is abstract tagged limited private;

procedure Put
  (Buffer : in out Root_Buffer_Type;
   Item   : in     String) is abstract;

In addition to Put, there are also Wide_Put, Wide_Wide_Put, Put_UTF_8, Wide_Put_UTF_16. And also New_Line, Increase_Indent, Decrease_Indent.

Outdated draft implementation

GNAT Community Edition 2020 and GCC 11 both provide a draft implementation that's incompatible with the Ada 2022 specification. For those versions, My_Put_Image looks like:

procedure My_Put_Image
  (Sink  : in out Ada.Strings.Text_Output.Sink'Class;
   Value : Source_Location)
is
   Line   : constant String := Value.Line'Image;
   Column : constant String := Value.Column'Image;
   Result : constant String :=
     Line (2 .. Line'Last) & ':' & Column (2 .. Column'Last);
begin
    Ada.Strings.Text_Output.Utils.Put_UTF_8 (Sink, Result);
end My_Put_Image;

References