comp.lang.ada
 help / color / mirror / Atom feed
From: Niklas Holsti <niklas.holsti@tidorum.invalid>
Subject: Ada conditional compilation and program variants
Date: Sun, 15 Apr 2018 16:07:45 +0300
Date: 2018-04-15T16:07:45+03:00	[thread overview]
Message-ID: <fjh151Fq7qrU1@mid.individual.net> (raw)
In-Reply-To: <eda4d4fa-8413-4e99-a0a6-d2a9a30d92d2@googlegroups.com>

(I changed the Subject to more apt. Long post follows, sorry.)

On 18-04-12 13:21 , Marius Amado-Alves wrote:
> The @ sign looks suspicially like a blackhole, swalling all material
> around it.
>
> Dmitry is contradictory (!) and confusing (all combinations of
> @-lines, really?)
>
> I don't know Janus.
>
> Given all these singular factoids I have no choice but to deem this
> conversation a subtle continuation of the joke.

I don't think so.

Starting from the joke, the thread passed on to consider several 
existing compiler features, and serious suggestions, for controlling 
which parts of the Ada source code are used by the compiler, and for 
what purposes, including

- the proposal for "ghost code" in Ada 2020

- other extensions to the "contract" features of Ada

- the inconvenience, in current Ada, of having to comment-in and 
comment-out debugging code, when the static-Boolean-conditional method 
does not work (eg. to include or exclude a "with" clause)

- Janus/Ada conditional compilation, with the "@" marker

- the risk that some combinations of the conditions for conditional 
compilation result in a variant of the source code that is syntactically 
or semantically illegal, with an example from Randy for "@"

- Dmitry's suggestions for changes to the Janus/Ada "@" to reduce that 
risk by requiring "@" to control only whole syntactic constructs (ie. to 
work on the grammar level rather than the lexical level)

- Dan'l's suggestions for using GLR parsing, or related fork/merge 
parsing methods, to ensure that all possible variants of the source code 
are syntactically legal, with a reference to an implementation for 
C-with-preprocessor that has successfully done this for the Linux kernel 
code (with an interesting connection to Dmitry's suggestion in that one 
essential part of this implementation is "ifdef-hoisting" where the 
ifdef scopes are expanded to control whole syntactic constructs).

It seems to me that a common question for the above points is how to 
manage "variants" of an Ada program (and, as Dan'l commented, "aspects" 
might be included, because they have a similar need to be separated from 
the rest of the program). Variants may be necessary to support different 
target systems, or different compilers, or just to choose which optional 
features (such as debugging or state-consistency checking) should be 
included in a particular build of the program.

The traditional solution is to use a preprocessor to conditionally 
select or transform the source code before the compiler sees it. This 
however means that the basic source code is not Ada, but 
Ada-with-preprocessor, and it also leads to differences between 
implementations, for example Janus/Ada with "@" versus the AdaCore/GNAT 
preprocessor commands. And of course all the old arguments against 
macro-based, text-oriented preprocessors are still valid.

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.

It further seems to me that this thread has identified some desirable 
requirements for an Ada conditional-compilation / variant-support 
feature, including:

1. It should be defined in the Ada standard, to ensure portability 
across compilers and to make it easier for IDEs to support it by eg. 
hiding or colorizing inactive parts of the source code.

2. It should be a part of the Ada language (the grammar), and should 
control whole syntactic constructs, unlike macro-based, text-oriented 
conditional compilation directives or preprocessors.

3. It should allow implementations to use GLR/FMLR-like parsing and 
analysis methods that can process all possible variants "at once" and 
check their legality as far as possible.

The variant-bodies method provides all of these, to some extent. It 
follows point 1 because all the source code is standard Ada. It follows 
point 2 because the boundaries of the variant code are package or 
subprogram boundaries. It follows point 3 because the static conformance 
of each body variant with all package declarations (and thus with any 
variant body of any other package) can be ensured by compiling each body 
variant separately, without having to build the whole program for all 
possible combinations of variant bodies. (This assumes that only bodies 
have variants, and declarations are invariant; unfortunately, 
declarations often need variants, too.)

On the other hand, the variant-bodies method fails to provide some 
aspects of the above requirements: it fails on point 1 because the 
method of choosing a particular variant of a body is not standardized; 
it supports point 2 weakly, because it is limited to variants that are 
complete bodies, and usually requires a dedicated source-code file for 
each variant; and for point 3 it forces implementations of the 
"all-variants-at-once" processors to use compiler/builder-specific 
methods for finding the possible variants of each body.

At present, I don't have a suggestion for a better method (than the 
variant-bodies method), but I think it could be a fruitful extension to 
Ada, especially if it it could support all three uses: variants 
(different implementations of a non-optional feature of the program), 
optional features, and aspects (by which I mean the centralized 
specification, at one point in the program, of distributed actions taken 
at several, appropriate points in the program).

In fact, I have one idea that could be part of this Ada extension: 
"package definitions". A package definition would be a new kind of 
compilable unit (but generating no code), usually in its own source-code 
file, which would bear a similar relation to a package declaration as a 
package declaration currently bears to the package body:

- A package declaration declares the things that the corresponding 
package body is required to implement.

- Analogously, a package definition would define, or specify, the things 
that the corresponding package declaration is required to declare.

However, this definition would be on a less specific level (more 
"generic") than the actual declarations, and would therefore allow 
different package declarations (variants) to conform to the same package 
definition.

For example, the definition of package A could require package A to 
declare a type T that is a discrete type, but the definition might not 
require anything more of T. Thus, one variant of package A might declare 
T as an integer range, while another could define T as an enumeration.

The package definition would be, for example:

    package definition A is
       type T is (<>);
       procedure F (Item : in T);
    end A;

and a possible conforming package declaration would be:

    package A is
       type T is (X, Y, Z);
       type S is new String;
       procedure Foo (Item : in T);
       procedure Bar (Item : in out T);
    end A;

The Ada RM is in fact full of package definitions, because the 
declarations of the predefined, standard packages shown in the RM 
contain text like

    subtype Any_Priority is Integer range /implementation-defined/;

which a package definition would state as (for example):

    subtype Any_Priority is Integer range <>;

Package definitions would be optional, but if a package definition is 
present then the package declaration must conform to it. This would 
allow the "variant bodies" method to be extended to allow also variant 
declarations, as long as the package definitions are invariant.

An interesting question is this: if package declaration or body B uses 
package A, and package A has a definition, how far can a compiler check 
that B uses A in legal ways if the compiler is allowed to look only at 
the definition of A, but not at the (or a) declaration of A?

If the compiler could check legality using only the package definitions 
of server packages, it would make it easier to ensure that all program 
variants are legal, by two separate and non-combinatorial steps:

- checking each variant package declaration against the (invariant) 
package definition, and

- checking each variant package body against the (invariant) package 
definitions of all other packages (those used by this body).

If checking the legality of how B uses A requires looking at the 
declaration of A (and not only at the definition of A), there is again a 
risk of combinatorial explosion in checking the legality of all 
(complete) program variants when there are variant package declarations.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .

  reply	other threads:[~2018-04-15 13:07 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-04-02  3:32 Interesting article on ARG work Randy Brukardt
2018-04-02 14:49 ` Dan'l Miller
2018-04-03 16:34   ` Bojan Bozovic
2018-04-03 22:33     ` Randy Brukardt
2018-04-04  2:12       ` Bojan Bozovic
2018-04-04 15:05       ` Dan'l Miller
2018-04-04 15:30         ` gerdien.de.kruyf
2018-04-04 16:09           ` Dan'l Miller
2018-04-04 22:30         ` Randy Brukardt
2018-04-04 22:43           ` Paul Rubin
2018-04-05  0:44             ` Mehdi Saada
2018-04-05 21:23               ` Randy Brukardt
2018-04-05  2:05           ` Bojan Bozovic
2018-04-05 22:12             ` Randy Brukardt
2018-04-06 13:35               ` Bojan Bozovic
2018-04-07  2:01                 ` Randy Brukardt
2018-04-05  7:21           ` Dmitry A. Kazakov
2018-04-05 22:18             ` Randy Brukardt
2018-04-06  7:30               ` Dmitry A. Kazakov
2018-04-07  2:25                 ` Randy Brukardt
2018-04-07 10:11                   ` Dmitry A. Kazakov
2018-04-07 15:27                     ` Dan'l Miller
2018-04-07 15:59                       ` Dmitry A. Kazakov
2018-04-08  0:14                         ` Dan'l Miller
2018-04-08  7:46                           ` Dmitry A. Kazakov
2018-04-08 19:48                             ` Dan'l Miller
2018-04-08 20:09                               ` Dmitry A. Kazakov
2018-04-09  3:50                                 ` Dan'l Miller
2018-04-09  6:40                                   ` Jan de Kruyf
2018-04-09  7:43                                   ` Dmitry A. Kazakov
2018-04-09 13:40                                     ` Dan'l Miller
2018-04-09 14:13                                       ` Dmitry A. Kazakov
2018-04-09 14:36                                         ` Dan'l Miller
2018-04-09 14:44                                           ` Dmitry A. Kazakov
2018-04-09 15:03                                             ` Dan'l Miller
2018-04-09 16:12                               ` Niklas Holsti
2018-04-09 16:30                                 ` Dmitry A. Kazakov
2018-04-09 16:45                                   ` Niklas Holsti
2018-04-09 17:33                                     ` Dan'l Miller
2018-04-09 19:47                                     ` Dmitry A. Kazakov
2018-04-09 20:24                                   ` Randy Brukardt
2018-04-10  8:17                                     ` Dmitry A. Kazakov
2018-04-09 18:08                                 ` Dan'l Miller
2018-04-09 21:17                                   ` Niklas Holsti
2018-04-09 22:09                                     ` Dan'l Miller
2018-04-10 19:23                                       ` Niklas Holsti
2018-04-10 19:46                                         ` Dan'l Miller
2018-04-15  7:50                                           ` Niklas Holsti
2018-04-15 13:31                                             ` Dan'l Miller
2018-04-15 18:37                                               ` Niklas Holsti
2018-04-09 20:14                       ` Randy Brukardt
2018-04-06 23:49               ` Dan'l Miller
2018-04-12 10:21                 ` Marius Amado-Alves
2018-04-15 13:07                   ` Niklas Holsti [this message]
2018-05-07  8:41                     ` Ada conditional compilation and program variants Jacob Sparre Andersen
2018-04-06 13:35 ` Interesting article on ARG work Marius Amado-Alves
2018-04-07  2:15   ` Randy Brukardt
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox