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
. @ .
next prev parent 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