Redefining the 'Image attribute

In Ada 2022 you can redefine 'Image attribute for your type. Corresponding syntax has been changed several times. Let's see how does it work in GNAT Community 2021.

Note

Attribute 'Image redefinition is supported by

  • GNAT Community Edition 2021 (using Text_Buffers)

  • GNAT Community Edition 2020 (using Text_Output.Utils)

  • GCC 11 (using Text_Output.Utils)

As an example, let's redefine 'Image attribute for the location in a source code. To do this we should provide a new Put_Image aspect on 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 is defined in 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;

Besides Put there are also Wide_Put, Wide_Wide_Put, Put_UTF_8, Wide_Put_UTF_16. And New_Line, Increase_Indent, Decrease_Indent.

Outdated draft implementation

GNAT Community Edition 2020 and GCC 11 both provide the draft implementation that is incompatible with Ada 2022 specification. In that case 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;