In Ada 2022, you can define string, integer, or real literals for your
types. The compiler will convert such literals to your type at run
time using a function you provide. To do so, specify one or more new
aspects:
Integer_Literal
Real_Literal
String_Literal
For our example, let's define all three for a simple type and see how
they work. For simplicity, we use a Wide_Wide_String component
for the internal representation:
pragma Ada_2022;
with Ada.Wide_Wide_Text_IO;
with Ada.Characters.Conversions;
procedure Main is
type My_Type (Length : Natural) is record
Value : Wide_Wide_String (1 .. Length);
end record
with String_Literal => From_String,
Real_Literal => From_Real,
Integer_Literal => From_Integer;
function From_String (Value : Wide_Wide_String) return My_Type is
((Length => Value'Length, Value => Value));
function From_Real (Value : String) return My_Type is
((Length => Value'Length,
Value => Ada.Characters.Conversions.To_Wide_Wide_String (Value)));
function From_Integer (Value : String) return My_Type renames From_Real;
procedure Print (Self : My_Type) is
begin
Ada.Wide_Wide_Text_IO.Put_Line (Self.Value);
end Print;
begin
Print ("Test ""string""");
Print (123);
Print (16#DEAD_BEEF#);
Print (2.99_792_458e+8);
end Main;
As you see, real and integer literals are converted to strings while
preserving the formatting in the source code, while string literals
are decoded: From_String is passed the specified string value.
In all cases, the compiler translates these literals into function
calls.
Now we can get the same result in Ada! But before we do, we need to
define a custom + operator:
pragma Ada_2022;
with Ada.Wide_Wide_Text_IO;
with Ada.Characters.Conversions;
procedure Main is
type My_Type (Length : Natural) is record
Value : Wide_Wide_String (1 .. Length);
end record
with String_Literal => From_String,
Real_Literal => From_Real,
Integer_Literal => From_Integer;
function "+" (Left, Right : My_Type) return My_Type is
(Left.Length + Right.Length, Left.Value & Right.Value);
function From_String (Value : Wide_Wide_String) return My_Type is
((Length => Value'Length, Value => Value));
function From_Real (Value : String) return My_Type is
((Length => Value'Length,
Value => Ada.Characters.Conversions.To_Wide_Wide_String (Value)));
function From_Integer (Value : String) return My_Type renames From_Real;
procedure Print (Self : My_Type) is
begin
Ada.Wide_Wide_Text_IO.Put_Line (Self.Value);
end Print;
begin
Print ("5" + 3);
end Main;
Jokes aside, this feature is very useful. For example it allows a
"native-looking API" for big integers.