Ada Print Port_Type - ada

how to put_line Port_Type as defined in g-socket.ads:492, please?
Ada.Text_io.Put_Line ("Port: " & Integer'Image(Port));
give me
found type "Port_Type" defined at g-socket.ads:492
xxx.adb:121:51: expected type "Standard.Integer"
Thanks
BR
Mark

You should be able to write
Ada.Text_IO.Put_Line ("Port: " & Port'Image);
or, if you’re using an older GNAT,
Ada.Text_IO.Put_Line ("Port: " & Port'Img);
’Image works for scalars; in Ada 2022 it works for composite types as well. There’s heavy stuff in ARM 2022 4.10, Image Attributes

Related

Late evaluation of function argument to formatted_string

Let's consider this MWE:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with GNAT.Strings; use GNAT.Strings;
with GNAT.Command_Line; use GNAT.Command_Line;
procedure Verbose_And_Image is
type T_Foo is tagged record
Member_1 : Natural := 13;
Member_2 : Float := 1.414;
Member_3 : Boolean := False;
Member_4 : Unbounded_String := To_Unbounded_String ("Foo");
Member_5 : Natural := 42;
end record;
function Image (Foo : in T_Foo) return String is
Message : Unbounded_String :=
"M1: " & Foo.Member_1'Image & " " &
"M2: " & Foo.Member_2'Image & " " &
"M3: " & Foo.Member_3'Image & " " &
"M4: " & Foo.Member_4 & " " &
"M5: " & Foo.Member_5'Image;
begin
return To_String(Message);
end Image;
Global_Foo : T_Foo;
Config : Command_Line_Configuration;
Verbose : aliased Boolean := False;
N_Elem : aliased Integer := 0;
procedure Debug (Message : in String) is
begin
if Verbose then
Put_Line (Message);
else
null; -- the program is quiet.
end if;
end Debug;
procedure Bar (I : in Integer; Foo : in out T_Foo) is
begin
Foo.Member_5 := I;
Debug ("I is: " & Image (Foo));
end Bar;
begin
Define_Switch (Config, Verbose'Access, "-v", Help => "Verbose");
Define_Switch (Config, N_Elem'Access, "-n:", Help => "Number of tries");
Getopt (Config);
Put_Line ("File argument was " & Verbose'Image);
for I in 1..N_Elem loop
Bar (I, Global_Foo);
end loop;
end Verbose_And_Image;
Compiling this example with gnatmake, we may "profile" our program with:
gnatmake -O3 verbose_and_image.adb
gcc -c -O3 verbose_and_image.adb
gnatbind -x verbose_and_image.ali
gnatlink verbose_and_image.ali -O3
$time ./verbose_and_image -n 19999999 > /dev/null # In "quiet"
real 0m8.282s
user 0m7.946s
sys 0m0.005s
$time ./verbose_and_image -v -n 19999999 > /dev/null # In verbose
real 0m19.481s
user 0m11.946s
sys 0m6.756s
In many cases, to "optimize" the code, some developers wrote everywhere:
procedure Bar (I : in Integer; Foo : in out T_Foo) is
begin
Foo.Member_5 := I;
if Verbose then
Debug ("I is: " & Image (Foo));
end if;
end Bar;
Which is indeed order of magnitude faster (though my example is not really precise):
$time ./verbose_and_image -v -n 19999999 > /dev/null
real 0m19.585s
user 0m12.146s
sys 0m6.655s
$time ./verbose_and_image -n 19999999 > /dev/null
real 0m0.027s
user 0m0.023s
sys 0m0.003s
Writing a dedicated Debug (Message : in String; Foo : in T_Foo) function leads to comparable performances.
My concern with this later form is that the thousands of if Level make the code horribly difficult to read (increasing the cyclomatic complexity) and most of them do not even make sense (no image evaluation inside).
It is also not acceptable to write those dedicated functions each time you want to print a message (plus the debugging is handled by a dedicated package).
Is there a way to offer a procedure based on Formatted_String (for instance) to allow a late evaluation of these Images when needed. Something like:
procedure Debug(format: in out Formatted_String, ...) is
begin
if Verbose then
for argument of arguments loop
format := format & argument'Image;
end loop;
Put_Line (-format);
end if;
end Debug;
So that, at any point, one may do:
Debug ( +"Debug %s", Foo);
Delaying the evaluation of the images to the Debug function and without the need to declare functions any time you want to print some debug message.
I would recommend against using "formatting strings", if possible.
They're too easy to screw-up and the compiler generally can't confirm that you're not making some mistake the way it can with Text_IO.Put_Line( "First-part " & Image(Object) & " second part.") or Text_IO.Put("First-part ")/Enumeration_IO.put(Object)/Text_IO.Put_Line(" second part.").
The way to handle the need for variable length inputs is typically via unconstrained arrays or Ada containers (esp vectors).

How do I enforce that a type hold only be a fixed set of non-contiguous values?

I was expecting this program to raise an error when I feed it 3 as a valid Scale value, but no such luck:
with Ada.Text_IO; use Ada.Text_IO;
procedure predicate is
type Scale is new Integer
with Dynamic_Predicate => Scale in 1 | 2 | 4 | 8;
GivesWarning : Scale := 3; -- gives warning
begin
Put_Line ("Hello World");
loop
Put_Line ("Gimme a value");
declare
AnyValue : Integer := Integer'Value (Get_Line);
S : Scale := Scale (AnyValue); -- no check done!
begin
Put_Line ("okay, that works" & S'Image);
end;
end loop;
end predicate;
I found this related question, but there the requirement is to use an enum., and the solution is to define an array from enum -> value.
I want something that gives me at least a warning at compile time, and allows me to check at runtime as well, and that raises an error if I try to put an invalid value in. Then, if I can use SPARK to prove that no invalid values can occur, I could turn off said checks. I was under the impression that this was how Static_ / Dynamic_ predicates work, so the example above took me by surprise.
You need to enable assertions. Either compile with -gnata or set an appropriate Assertion_Policy
pragma Assertion_Policy(Dynamic_Predicate => Check);

Ada, raised CONSTRAINT_ERROR : bad input for 'Value: "well."

I am unable to get the following script to return my input value; I've looked up ARM as well as John Barnes book but to no avail. In theory it should work.
Anyone know why? I'm a newby so the Barnes book and the ARM are probably too advanced for me.
with Ada.Text_IO;
use Ada.Text_IO;
procedure ron is
A : Character;
begin
Put_Line ("Hi Ron, how are you?");
A := Character'Value (Get_Line);
Put_Line ("So you feel" &
Character'Image (A));
end ron;
--TERMINAL OUTPUT
--ronhans#amante ~/Desktop $ gnatmake -gnat2012 ron.adb
--gcc-4.8 -c -gnat2012 ron.adb
--gnatbind -x ron.ali
--gnatlink ron.ali
--ronhans#amante ~/Desktop $ ./ron
--Hi Ron, how are you?
--well.
--raised CONSTRAINT_ERROR : bad input for 'Value: "well."
If you look in the LRM, you will see that Ada.Text_IO.Get_Line returns a String:
with Ada.Text_IO;
procedure Ron is
begin
Ada.Text_IO.Put_Line ("Hi Ron, how are you?");
declare
Reply : constant String := Ada.Text_IO.Get_Line;
begin
Ada.Text_IO.Put_Line ("So you feel " & Reply & "?");
end;
end Ron;
The problem with you program is that you try to put an array of characters into a single character. Instead of of using A : Character, try to define an array type something like
type Character_Array_T (1 .. 10) of Character;
...
A : Character_Array_T;
or use
with Ada.Strings.Unbounded;
...
A : Ada.Strings.Unbounded.Unbounded_String;
I suggest the use of an unbounded string, so that the input is not bounded to some specific string length, if your intention is to read out an input several times. Ada type string requires you to specify the string length and this length is exactly the number of characters this string should contain.
See Wiki, unbounded strings and Unbounded string handling for the reference.

How to Loop to Get an int from stdinput, ignoring white space

So I can easily grab the int value I am looking for from my .txt file through standard input but when there is a white space (or multiple white spaces) before it, it doesn't work and a data error occurs, Since its an integer though, my code below which works for a grabbing a string, does not work when I put an int in there because you cannot compare an Int to a String. Any ideas on workarounds?
Until_loop: -- Loop to get chars even if space is between
loop
get(int_variable);
exit Until_loop when int_variable) /= " "; --won't work
end loop Until_loop;
ajb was right integers already go the space checking, my code was only messing it up. No loop needed for getting ints but it works well for String's/Characters.
So you can use the 'Value attribute to go from string to int and 'Image to go from int to string. These are attributes in Ada. Learning how to effectively use attributes will definitely increase your Ada productivity.
Basically I think this does what you want. You can read the string in and convert the string to an integer with
with Ada.Text_IO; use Ada.Text_IO;
procedure Foo is
Str: String(1 .. 10) := (others => ' ');
Last_Char : Integer;
begin
Put("Enter num: ");
Get_Line(Str, Last_Char);
Put_Line("Str = """ & Str & """");
Put_Line("Last = " & Integer'Image(Last_Char));
Put_Line("The num is " & Integer'Value(Str));
end Foo;
It yields the output:
Enter num: 1239
Str = "1239 "
Last_Char = 4
The num is 1239
If you want help iterating on this idea and morphing your original question into a slightly different method, let me know. I will gladly work with you on this ;)

Ada linker not letting me call my procedure

Here is my code:
procedure String_To_Int(str: String) is
str_length : Integer := str'Size / 8;
ASCII_Values_Array: array (Integer range 1 .. str_length) of Integer;
begin
Text_Io.Put_Line(str & " has a length of " & natural'image(str_length));
for x in 1 .. str_length loop
ASCII_Values_Array(x) := Character'Pos(str(x));
Text_Io.Put_Line(natural'image(ASCII_Values_Array(x)));
end loop;
end String_To_Int;
and I am trying to call it with:
String_To_Int(str => "abcdefghijklmnopqrstuvwxyz");
but the compiler is telling me:
Saw '(', expected: , :
And I have no clue what is wrong about how I am calling my procedure. I have looked at many other examples of procedure calls and this looks exactly the same. Any help is appreciated!
There's something you aren't telling us.
./test_sti;
abcdefghijklmnopqrstuvwxyz has a length of 26
97
98
99
...
121
122
Now you don't say what you're actually doing, but here's what I did.
I called String_To_Int from another procedure, in a file test_sti.adb.
with String_To_Int;
procedure test_sti is
begin
String_To_Int(str => "abcdefghijklmnopqrstuvwxyz");
end;
Note that String_To_Int is a separate procedure, in its own file, so the with clause tells the compiler to look for it. I could have declared it locally, i.e. between "is" and "begin" and saved both the files below, but separation is probably better design.
Now anything "with"ed will have both a specification and a body - in this case, specification string_to_int.ads :
procedure String_To_Int(str: String);
and body string_to_int.adb :
with Ada.Text_IO;
use Ada;
procedure String_To_Int(str: String) is
str_length : Integer := str'Size / 8;
ASCII_Values_Array: array (Integer range 1 .. str_length) of Integer;
begin
Text_Io.Put_Line(str & " has a length of " & natural'image(str_length));
for x in 1 .. str_length loop
ASCII_Values_Array(x) := Character'Pos(str(x));
Text_Io.Put_Line(natural'image(ASCII_Values_Array(x)));
end loop;
end String_To_Int;
and to build the lot, simply
gnatmake test_sti.adb
and the compiler works out its own dependencies, no Makefile necessary.
It's actually a bit odd (but perfectly legal) to have a separate "compilation unit" like this for just one procedure. More normally it would either be declared locally, or it would be a part of a package - either a collection of utilities like Ada.Text_IO, or something like a class if you are familiar with Java or C++.
Incidentally, String_To_Int is a very odd procedure : instead of declaring its variables as
str_length : Integer := str'Size / 8;
ASCII_Values_Array: array (Integer range 1 .. str_length) of Integer;
it's cleaner to use the attributes more consistently:
str_length : constant natural := str'Length;
ASCII_Values_Array: array (str'range) of Integer;
and express the loop condition as
for x in str'range loop

Resources