This post is a part of the Ada 2020 series.
You can launch this notebook with Jupyter Ada Kernel by clicking this button:
Firstly, let's activate Ada 2020 support in the compiler.
Usually we do this by -gnat2020
option in compiler command line or in the project file
(preferred). But in this notebook we will do this by the pragma Ada_2020
.
Also we will need the Text_IO
package.
pragma Ada_2020;
with Ada.Text_IO;
In Ada 2020 you can redefine 'Image
attribute for your type. And GNAT Community Edition 2020 does it in its-own (rather ugly from my point of view) way. It differs from ARM 2020 Draft.
Initially,
ARG used Ada.Streams.Root_Stream_Type'Class
to write a string image there. I didn't like this approach, because it's too low-level, error prone and nonportable, so I wrote a proposal. I proposed to add a new abstraction Output_Text_Stream, where you can write Wide_Wide_String to. No encodings games, not CR/LF handling, no ridiculous UTF8_Strings. I have no explanation why the proposal isn't good enough nor argument why it should be done in a different way. Instead the Standard was changed by adding Root_Buffer_Type, where you can Put
a Wide_Wide_String
and Get
a String
with no idea how it will be converted.
So, how GNAT CE 2020 does this? It does in a complete different way, I would say.
Firstly, you need some package:
with Ada.Strings.Text_Output.Utils;
Then, for your type you will define a new aspect Put_Image
:
package Source_Locations is
type Source_Location is record
Line : Positive;
Column : Positive;
end record
with Put_Image => My_Put_Image;
procedure My_Put_Image
(Sink : in out Ada.Strings.Text_Output.Sink'Class;
Value : Source_Location);
end Source_Locations;
package body Source_Locations is
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;
end Source_Locations;
Let's define some object
Line_10 : Source_Locations.Source_Location := (Line => 10, Column => 1);
Now print its 'Image
Ada.Text_IO.Put_Line ("Text position: " & Line_10'Image);
Text position: 10:1
Looks like it works. But, will it work in non-UTF-8 environment? No body knows, because it's implementation defined, I guess.
Let's see how Ada.Strings.Text_Output.Sink
is defined.
type Sink (<>) is abstract tagged limited private;
type Sink_Access is access all Sink'Class with Storage_Size => 0;
-- Sink is a character sink; you can send characters to a Sink.
-- UTF-8 encoding is used.
procedure Full_Method (S : in out Sink) is abstract;
procedure Flush_Method (S : in out Sink) is abstract;
So,
- How to write strings to the
Sink
? - Why should I use UTF-8?
- Will it work in non-utf-8 environment?
- How to write a muliline image in a portable way?
- Will it do a correct Unicode handling for me?
- Can I use my-own
Sink
to stream value image into a DB or XML, for instance? - Can we convince the ARG to do this better or just open the discussion to the community?
I don't know. Do I like this? Not at all.
Do you?
- Ada Reference Manual 2020 Draft
- AI12-0020-1
- AI12-0340-1
- RFC and comments
- Unicode Strings in Ada 2012
Do you like this? Support us on patreon!