From Newsgroup: comp.lang.ada
On Sat, 16 Oct 2021, Simon Wright wrote:
""Dmitry A. Kazakov" <
mailbox@dmitry-kazakov.de> writes:
Why do you think people keep on asking for Ada preprocessor in c.l.a?
Certainly not something I've noticed"
Here we go again!
An Adaist said to me that that Adaist wants to be able to write a subtype constraint like:
subtype a_subtype is a_type range 0 .. [the minimum of
a_type'Last and 16#1234_5678#];
I wrote to that Adaist . . .
"How about the attached solution?
One approach which should work is to exploit a deferred constant (
HTTP://archive.AdaIC.com/docs/craft/html/ch09.htm#9.5
) but this does not actually work for [a_type . . .].
Randy Brukardt wrote in comp.lang.ada in 2021:
"you're talking
about switching implementations of a single Ada spec. We've done that
going back to the beginning of Ada time; it's managed by decent build
tools and has gotten pretty simple in most Ada compilers."
He wrote in 2018:
"The best way to do this in Ada is with different package bodies (and sometimes specs) for each target. That's how Janus/Ada is designed, and it works great. I know the GNAT project system even has facilities to make
this happen automatically (by selecting the unit to compile based on a
version id)."
Cf. Shark8 wrote in 2019:
"Ada has no preprocessor; this was a deliberate design-decision.
The way such conditional variance is typically handled is through the tooling/project system. (e.g. by specifying a particular implementation [ADB file] to associate with the corresponding specification for that
particular compilation.)"
Cf. Rolf wrote in 2019:
"You typically define or set preprocessor variables at the command line
(e.g. -XDAYSOFOURLIVES=1000). GNAT uses a configuration file (gpr file) to set some variables."
Various persons - e.g. Bob Kitzberger and Ada Core Technologies - suggest various approaches. E.g. one good suggestion in
info gnat_ug
is:
"In some cases it may be necessary to conditionalize declarations to meet different requirements. For example we might want a bit string whose
length is set to meet some hardware message requirement.
This may be possible using declare blocks controlled by conditional
constants:
if Small_Machine then
declare
X : Bit_String (1 .. 10);
begin
...
end;
else
declare
X : Large_Bit_String (1 .. 1000);
begin
...
end;
end if;
Note that in this approach, both declarations are analyzed by the
compiler so this can only be used where both declarations are legal,
even though one of them will not be used."
Alas, Ada Core Technolgies omits an explanation as to how to conditionally
set Small_Machine!
Holsti wrote in 2018:
"Barring preprocessors, a practical solution, which I often use and which
I believe is widely used, is to isolate the features and variant code into their own packages (or separate subprograms), to provide variant bodies
for those packages (eg. for different targets, or to include or omit debugging), and to guide the Ada compiler to select the desired bodies
through some kind of search path (eg. ADA_INCLUDE_PATH for GNAT, or the
GNAT project files for gprbuild). This often works well, but also often
leads to some amount of duplicated invariant code in the various package bodies, because isolating exactly and only the variant code into packages would create a mess of very many small packages, possibly conflicting with
the logical modular structure of the program. Furthermore, just as for the preprocessor method, this variant-bodies method is not standardized and is therefore supported in different ways by different IDEs and compilers."
I imagine that one approach could exploit
HTTPS://AdaIC.org/resources/add_content/standards/22rm/html/RM-7-3-3.html
info gnat_ug
hints at some good solution which I do not show:
"Since a powerful subset of Ada expression
notation is usable for creating static constants, clever use of this
feature can often solve quite difficult problems in conditionalizing compilation".
Instead, I base this attached solution on Sections
Integrated Preprocessing
and
Form of Input Text for ‘gnatprep’
in
info gnat_ug
"
along with attachments like . . .
with a_package;
with Ada.Text_IO;
procedure How_Small is
package a_type_IO is new Ada.Text_IO.Integer_IO(a_type);
begin
Ada.Text_IO.Put("a_subtype'Last is ");
a_type_IO.Put(a_package.a_subtype'Last);
end How_Small;
-- minimum_of_a_type_Last_and_1234_5678 is a program with --platform-independent
--source code which outputs the platform-dependent value of
-- a_subtype'Last
with Ada.Text_IO;
procedure minimum_of_a_type_Last_and_1234_5678 is
Minimum_Answer : a_type := 16#1234_5678#;
package a_type_IO is new Ada.Text_IO.Integer_IO(a_type);
begin
if a_type'Last < Minimum_Answer then
Minimum_Answer := a_type'Last;
--Hmm. I am looking at this procedure again while not fully awake, and now --it is iffy that if a_type'Last < Minimum_Answer could be true because
-- Minimum_Answer already was assigned a value of the same type. Hmm.
end if;
a_type_IO.Put(Minimum_Answer, Width => 1);
end minimum_of_a_type_Last_and_1234_5678;
package a_package is
--This package demonstrates one way to have a platform-dependent
--constant upper bound.
--This package can be compiled by for example . . .
-- gnatmake minimum_of_a_type_Last_and_1234_5678
-- gnatmake -gnateDValue_Via_A_Preprocessor=`./minimum_of_a_type_Last_and_1234_5678` How_Small
-- using a Bourne-Again SHell (BASH).
Platform_Specific_Constant : constant a_type := $Value_Via_A_Preprocessor;
subtype a_subtype is a_type range 0 .. Platform_Specific_Constant;
end a_package;
Holsti refers to code cloning ("duplicated invariant code"). Doctor Erhard Ploedereder works on Ada and code-clone detectors. I myself wrote
package a_type_IO is new Ada.Text_IO.Integer_IO(a_type);
twice above. This is not a fault of Ada's. Ahem. Pot calling the kettle
black!
(S.
HTTP://Gloucester.Insomnia247.NL/ fuer Kontaktdaten!)
--- Synchronet 3.21f-Linux NewsLink 1.2