• build-dependant deferred constants

    From thanks-to@thanks-to@Taf.com to comp.lang.ada on Wed Apr 1 19:43:00 2026
    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
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.ada on Wed Apr 1 20:46:16 2026
    From Newsgroup: comp.lang.ada

    On Wed, 1 Apr 2026 19:43:00 -0000 (UTC), Nioclás Pól Caileán de
    Ghloucester wrote:

    Cf. Shark8 wrote in 2019:
    "Ada has no preprocessor; this was a deliberate design-decision.

    A C-style preprocessor is indeed a horrible, clunky, fragile,
    trouble-prone mechanism.

    The better way is AST-level macros (“homoiconicity”), as pioneered by
    Lisp.

    If Rust can implement AST-level macros, why couldn’t Ada?
    --- Synchronet 3.21f-Linux NewsLink 1.2