CVS difference for acs/ac-00052.txt

Differences between 1.1 and version 1.2
Log of other versions for file acs/ac-00052.txt

--- acs/ac-00052.txt	2003/01/24 04:14:26	1.1
+++ acs/ac-00052.txt	2003/09/30 02:01:10	1.2
@@ -68,3 +68,324 @@
 be useful in other situations too, but I don't know for sure.
 
 ****************************************************************
+
+!topic Proposal for "semi-private" types
+!reference RM95-3.2.1, RM95-12.5(2)
+!from Niklas Holsti 03-09-26
+!keywords private types, generic formals, client-server contracts
+!discussion
+
+Summary
+
+   In addition to the current "fully private" private types, it should
+   be allowed to declare types that are "partially private" in the
+   same sense and same syntax as for generic formal type parameters.
+
+   For example, in the public part of a package declaration we could
+   write 'type T is (<>);' or 'type T is range <>;' to inform the
+   clients that the type T is a discrete type or a signed integer
+   type without revealing full details such as the actual enumeration
+   literals or numerical ranges. The full declaration would be in the
+   private part of the package declaration, as for fully private types.
+
+
+Existing similar constructs
+
+   1. Generic formal type parameters.
+
+
+Similar or related other proposals
+
+   1. Being able to declare 'type T is tagged;' so that T'Class can
+      be used before the full declaration of T.
+
+
+Expected impact on compilers
+
+   Changes to the type-visibility and freezing definitions. However,
+   similar rules already exist for generics. Code generation for a
+   package declaration may be affected, because the full definition of
+   some types is not visible until the private part is compiled. No
+   difference in code generation for the body of a package, because
+   the type is then fully defined.
+
+
+Motivation
+
+   When an application is composed from software components, possibly
+   implemented by different parties or with a variety of
+   implementations for different platforms or variants of the
+   application, there is a kind of contract relationship between
+   "server" packages (the ones that provide types and operations) and
+   their "client" packages (the ones that use these types and
+   operations). This proposal focuses on the role of types in this
+   contract.
+
+   The server packages promise to provide certain types with certain
+   properties, and the client packages are designed to rely on the
+   existence and properties of these types. It is desirable for the
+   contract to be flexible so that the clients rely only on a minimal
+   and well defined set of type properties. This makes it possible to
+   change server implementations without forcing changes in the
+   clients. Just recompiling and relinking the application will be
+   enough.
+
+   Server implementations may need to vary depending on the target
+   platform, the geographic location, the specific variant of the
+   application and other similar reasons.
+
+   Contract flexibility is currently achieved mainly by hiding data
+   and type structures. The servers provide abstract data types
+   instead of concrete ones. Currently in Ada, there are only three
+   choices for exposing or hiding a type:
+
+      (1) the type is fully public;
+      (2) the type is fully private; or
+      (3) the type has some private parts and some public parts.
+
+   The last choice only applies to record and tagged types, where
+   some components may be of a private type and others of a public
+   type, and to array types where the index type may (and must) be
+   public while the component type can be private or a record with
+   some private and some public parts.
+
+   We will here ignore the third choice because it only amounts to
+   an aggregation of lower-level types where at the bottom level
+   only the first two choices (fully public or fully private) are
+   possible.
+
+   The problem is that if the type is fully public, its declaration
+   may reveal properties that are not meant to be part of the contract.
+
+   For example, assume that the contract means to define a discrete
+   type that can be used as an array index. If this type is declared
+   as a public type, the declaration must reveal whether the type is
+   an enumerated type, a signed integer type or a modular integer type.
+   It must also reveal the enumeration literals, the parent type if
+   any,  or the actual integer ranges, as the case may be.
+
+   The clients may inadvertently come to rely on properties of the type
+   that are not meant to be in the contract and actually vary across
+   different server implementations, making the clients incompatible
+   with some server implementations. This is bad, since it limits the
+   reusability, maintainability and portability of the components and
+   the entire application.
+
+   On the other hand, if the type is fully private then the clients
+   can only use the type through server operations. Basic attributes
+   such as 'First and 'Last must be provided through server functions,
+   and no private type can be used as an array index or as the discrete
+   subtype in a "for .. loop" statement. This makes it harder to design
+   and implement applications that use private types, which leads to
+   an undesirable trade-off between short-term concerns (use public
+   types to achieve quick and cheap design and coding, fast execution,
+   small code size) and long-term concerns (use private types to help
+   maintenance, reuse, porting).
+
+   The proposed solution is inspired by the contract between a generic
+   and its users (instantiators), which is very similar to the contract
+   between servers and clients:
+
+   - The generic formals part corresponds to the contract. It reveals
+     only some of the properties of the types in the contract.
+
+   - The rest of the generic corresponds to the client. It is
+     allowed to use only those type properties that were revealed
+     in the formals part.
+
+   - An instantiation of the generic corresponds to an implementation
+     of the server. It provides concrete types that have the properties
+     revealed and required in the contract. The types also have other
+     properties, but the generic mechanism guarantees that the precise
+     nature of these other properties is irrelevant to the proper
+     working of this instance of the generic.
+
+   The proposal is simply this: Ada should allow, in the public part
+   of a package declaration, some of the same kinds of incomplete or
+   partially revealing type declarations as in generic formal type
+   parameters.
+
+   Any package that "withs" this package would then have the same
+   knowledge about the declared entities as a generic unit has about
+   its formals. However, as for the current fully private types, the
+   full declarations would have to be stated in the private part of
+   the package declaration, so the compiler would still, after
+   compiling the package declaration, have full knowledge of the
+   declared entities.
+
+   Only the analogues of formal type declarations are proposed.
+   The other forms of generic formal parameter declarations are not
+   needed in this context because ordinary declarations can be used
+   instead; it is only the "partially private" aspect of formal types
+   that is currently missing.
+
+
+Example 1: Bongo-drum scheduling
+
+   package Bongo_Drum_Scheduling is
+   -- Provides thread scheduling according to the bongo-drum
+   -- method. The properties of this method may depend on the
+   -- processing platform, viz. how many drums there are, how
+   -- far the drum-beaters can count priorities, and how many
+   -- dancing threads can fit in the circle.
+
+      type Drum_Index is (<>);
+      -- Identifies a drum. You can use the fact that it is
+      -- a discrete type, but you can and must use 'First and
+      -- 'Last to find out the range, because it is private.
+
+      type Priority is range <>;
+      -- The priority of a thread. You can rely on it being an
+      -- integral type, so you can use addition and subtraction,
+      -- but you can and must use 'First and 'Last to find out
+      -- how many priority levels there are.
+
+      type Circle_Position is mod <>;
+      -- The position of a dancing thread in the circle around the
+      -- bongo players. You know it is a circle, but you must
+      -- use 'Modulus or 'Last to find out the circumference
+      -- (number of dancer positions).
+
+      type Thread is new Controlled with private;
+      -- The thread type is controlled, just so you know,
+      -- but I am not showing you the extension, not even as
+      -- a private type.
+
+      type Beat is record
+         Numerator   : Circle_Position;
+         Denominator : Circle_Position;
+      end record;
+      -- Defines one component of the dancing/scheduling rhythm.
+
+      type Rhythm is array (Drum_Index) of Beat;
+      -- Bom-bom bom-bom-bom, tap tap, scratch and skip.
+      -- You know a lot about this type:
+      --  o  It is a one-dimensional constrained array.
+      --  o  Its component type is a record with two
+      --     components named Numerator and Denominator,
+      --     both of the modular type Circle_Position.
+      -- You also _do not_ know many things:
+      -- o   The array length (you can and must use 'Length)
+      -- o   The index range (you can and must use 'Range or
+      --     'First or 'Last)
+      -- o   The modulus of Circle_Position.
+
+      ... operation declarations omitted
+
+   private
+
+      type Dum_Index is (Tiny, Big, Medium);
+      -- In this set, we have three drums.
+
+      type Priority is new Natural;
+      -- We have lots of priorities.
+
+      type Circle_Position is mod 9;
+      -- Nine threads fit in the circle.
+
+      type Thread is new Controlled with record
+         ... new components
+      end record;
+
+      ... and so on.
+
+   end Bongo_Drum_Scheduling;
+
+
+Example 2: Some Ada predefined packages.
+
+   The proposed extension could be used in the LRM itself, to
+   make the public parts of the predefined packages real Ada
+   and hide the "implementation defined" remarks in the private
+   parts. For example:
+
+      package Standard is
+         ...
+         type Integer is range <>;
+         -- Shows that Integer is a signed integer type, but
+         -- the actual bounds are private.
+
+         type Float is digits <>;
+         -- Shows that Float is a floating-point type, but the
+         -- actual precision is private.
+         ...
+      private
+         implementation-defined
+      end Standard;
+
+   (Note: RM95-A.1(48) states that "Standard has no private part".
+   I do not know if this is a deep requirement or merely a note
+   about the current definition of Standard.)
+
+   Another example:
+
+      package Interfaces.C is
+         ...
+         type int is range <>;
+         ...
+      private
+         implementation-defined
+      end Interfaces.C;
+
+
+Work-around designs
+
+   The server-client type-contract can be implemented in other ways,
+   of course. Some of these ways are:
+
+   1. Use fully public types and separate the intentionally public
+      and accidentally public properties in documentation or comments.
+      This does not give a compile-time check that the clients use
+      only the intentionally public (contracted) type properties.
+
+   2. Use fully private types and implement all the necessary
+      operations on these types. This is limited by the inability to
+      overload assignment, indexing and literals.
+
+   3. Write all the client packages as generic packages with all
+      the server-provided items as generic formals. This is quite
+      cumbersome and prevents any bidirectional interaction between
+      clients and servers. where the servers use some items provided
+      by the clients, for example composite types that combine
+      items from servers and clients or call-back operations that
+      let servers activate clients. Such bidirectional interaction
+      is usually necessary, in my experience.
+
+
+Possible extensions
+
+   Perhaps a wider syntax than in generics could be used, with more
+   options for revealing and hiding properties. For example:
+
+      type Apples_Count is new Natural range <>;
+      -- Apples are counted with a type derived from Natural,
+      -- but we are not showing the range, so use 'First and 'Last.
+
+      type Positive_Count is range 1 .. <>;
+      -- A count, starting from 1, with a private upper bound.
+
+      subtype Index is Integer range <>;
+      -- A subtype of Integer, with private bounds.
+
+
+Possible problems
+
+   The current freezing rules may imply that some types must be
+   fully defined before the private part is compiled. For example,
+   if a type declared as "type Num is range <>" is then used as the
+   index type in an array declaration, the compiler may not know
+   how to implement the array type because the 'Size of the index
+   type is not known yet, being defined in the private part.
+
+****************************************************************
+
+From: Adam Beneschan
+Sent: Friday, September 26, 2003  3:34 PM
+
+Deja vu all over again?  I posted the following to Ada-Comment on
+October 11, 2002.  I was later told that this was essentially the same
+as Ada9X revision request #229, submitted on July 21, 1989.
+
+[Editor's note: see above.]
+
+****************************************************************

Questions? Ask the ACAA Technical Agent