From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=unavailable autolearn_force=no version=3.4.4 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!feeder.eternal-september.org!news.swapon.de!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: Niklas Holsti Newsgroups: comp.lang.ada Subject: Ada conditional compilation and program variants Date: Sun, 15 Apr 2018 16:07:45 +0300 Organization: Tidorum Ltd Message-ID: References: <1b44444f-c1b3-414e-84fb-8798961487c3@googlegroups.com> <62ee0aac-49da-4925-b9aa-a16695b3fc45@googlegroups.com> <9879872e-c18a-4667-afe5-41ce0f54559f@googlegroups.com> <0520137a-4d39-440f-931b-b41c880c49d4@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-Trace: individual.net RnYXl3FqZ+jFo6bVp8az+QpgSJ3LAXPftnBN0lGgOChsqiXoaf Cancel-Lock: sha1:ZSZT6+VAvRvgQYkdSAqn71G8Xes= User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:45.0) Gecko/20100101 Thunderbird/45.8.0 In-Reply-To: Xref: reader02.eternal-september.org comp.lang.ada:51511 Date: 2018-04-15T16:07:45+03:00 List-Id: (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 . @ .