From ff629a94244d2aa1fb34422ebfd4094696bf292a Mon Sep 17 00:00:00 2001 From: Pat Rogers Date: Fri, 17 Jan 2025 11:42:47 -0600 Subject: [PATCH] Change the "Solution" heading to "Implementation(s)" to avoid the context of solving a problem (instead of expressing an idiom). Make controlling_obj_initialization_creation.rst have the same outline headings as the other idiom entries, especially change heading "Requiring Initialization by Clients" to "Implementation(s)" Change "solution" to alternative words, usually either "implementation" or "approach". --- .../chapters/abstract_data_machines.rst | 4 +- .../chapters/abstract_data_types.rst | 6 +-- .../chapters/component_access_to_rec_objs.rst | 20 ++++---- ...ctor_functions_for_abstract_data_types.rst | 16 +++--- ...ontrolling_obj_initialization_creation.rst | 50 +++++++++---------- .../essential_idioms_for_packages.rst | 4 +- .../chapters/inheritance_idioms.rst | 14 +++--- .../chapters/interrupt_handling.rst | 34 ++++++------- .../ada-idioms/chapters/introduction.rst | 4 +- .../chapters/programming_by_extension.rst | 4 +- ...de_from_generic_package_instantiations.rst | 4 +- .../ada-idioms/chapters/type_punning.rst | 12 ++--- 12 files changed, 87 insertions(+), 85 deletions(-) diff --git a/content/courses/ada-idioms/chapters/abstract_data_machines.rst b/content/courses/ada-idioms/chapters/abstract_data_machines.rst index 0668a78cf..392dd7e63 100644 --- a/content/courses/ada-idioms/chapters/abstract_data_machines.rst +++ b/content/courses/ada-idioms/chapters/abstract_data_machines.rst @@ -53,8 +53,8 @@ Machine (ADM). The Abstract Data Machine was introduced by Grady Booch [1]_ as the Abstract State Machine, but that name, though appropriate, encompasses more in computer science than we intend to evoke. -Solution --------- +Implementation(s) +----------------- The ADM is similar to the ADT idiom in that it presents an abstraction that doesn't already exist in the programming language. diff --git a/content/courses/ada-idioms/chapters/abstract_data_types.rst b/content/courses/ada-idioms/chapters/abstract_data_types.rst index 9f4878a9d..38a0b77a4 100644 --- a/content/courses/ada-idioms/chapters/abstract_data_types.rst +++ b/content/courses/ada-idioms/chapters/abstract_data_types.rst @@ -68,8 +68,8 @@ likely introduce new bugs. These disadvantages argue for an alternative. That is the purpose of this next idiom, known as the Abstract Data Type (ADT) [1]_, [2]_. -Solution --------- +Implementation(s) +----------------- Abstraction is one of the central principles of software engineering because it is one of the primary ways that humans manage complexity. The idea is to @@ -344,7 +344,7 @@ type can be private, as illustrated by the client expectation for array indexing in Ada prior to Ada 2012. Not every type should be private, for example those that are explicitly numeric. But the ADT should be the default design idiom when -decomposing a problem into a solution. +composing a solution. Cons ---- diff --git a/content/courses/ada-idioms/chapters/component_access_to_rec_objs.rst b/content/courses/ada-idioms/chapters/component_access_to_rec_objs.rst index 676bf0b97..fac7ae32f 100644 --- a/content/courses/ada-idioms/chapters/component_access_to_rec_objs.rst +++ b/content/courses/ada-idioms/chapters/component_access_to_rec_objs.rst @@ -73,14 +73,14 @@ defining major types, for the good reasons given in that idiom entry. There's no reason not to use an ADT in this case so we will. -Solution +Implementation(s) ----------------- -As mentioned, the solution applies to enclosed components of both task types +As mentioned, the implementation approach applies to enclosed components of both task types and protected types. We will continue the discussion in terms of protected types. -The solution has two parts: +The implementation has two parts: 1. An access discriminant on the PO type, designating the enclosing record's type. That part is straightforward. @@ -118,7 +118,7 @@ two parts: The record type named :ada:`Device` contains a component named :ada:`X`, arbitrarily of type :ada:`Integer`, and another component :ada:`C` that is of -protected type :ada:`Controller`. Part #1 of the solution is the access +protected type :ada:`Controller`. Part #1 of the implementation is the access discriminant on the declaration of the protected type :ada:`Controller`: .. code-block:: ada @@ -185,7 +185,7 @@ discriminant :ada:`Encloser` to get to the current instance's :ada:`X` component. (We could express it as :ada:`Encloser.all.X` but why bother. Implicit dereferencing is a wonderful thing.) -That's the solution. Now for some necessary details. +That's the implementation. Now for some necessary details. Note that we declared type :ada:`Device` as a limited type, first in the visible part of the package: @@ -212,11 +212,11 @@ a component that uses the :ada:`Access` attribute in this way. Also note that any type that includes a protected or task object is limited, so a type like Device will necessarily be limited in any case. -The type need not be tagged for this idiom solution, but it must be +The type need not be tagged for this approach, but it must be limited in both its partial view and its full view. More generally, a tagged type must be limited in both views if it is limited in either view. -For the idiom solution to be legal, the type's completion in the private part +For the idiom implementation to be legal, the type's completion in the private part must not merely be limited, but actually *immutably limited*, meaning that it is always truly limited. There are various ways to make that happen (see :aarm22:`AARM22 7.5 (8.1/3) <7-5>` ) but the easiest way to is to include the @@ -532,11 +532,11 @@ inherited IO pin components. Pros ----------------- -The solution is directly expressed, requiring only an access discriminant and +The implementation is directly expressed, requiring only an access discriminant and the current instance semantics of :ada:`type_name'Access`. Although the real-word example is complex |mdash| multiple discriminants are -involved, and a type extension |mdash| the idiom solution itself requires little +involved, and a type extension |mdash| the implementation itself requires little text. Interrupt handling is relatively complex in any language. @@ -554,7 +554,7 @@ Relationship With Other Idioms This idiom is useful when we have a record type enclosing a PO or task object. If the :ref:`Abstract Data Machine (ADM) ` would instead be appropriate, the necessary visibility can be achieved without -requiring this idiom solution because there would be no enclosing record type. +requiring this implementation approach because there would be no enclosing record type. But as described in the ADM discussion, the :ref:`ADT approach ` is usually superior. diff --git a/content/courses/ada-idioms/chapters/constructor_functions_for_abstract_data_types.rst b/content/courses/ada-idioms/chapters/constructor_functions_for_abstract_data_types.rst index 37e045a0e..efb1e7f95 100644 --- a/content/courses/ada-idioms/chapters/constructor_functions_for_abstract_data_types.rst +++ b/content/courses/ada-idioms/chapters/constructor_functions_for_abstract_data_types.rst @@ -208,20 +208,20 @@ that sufficient constructor functions are possible. Therefore, a general design idiom is required for defining constructor functions for concrete tagged Abstract Data Types. -Solution --------- +Implementation(s) +----------------- -The general solution uses functions for constructing objects but prevents these +The general approach uses functions for constructing objects but prevents these functions from being inherited. The problem is thus circumvented entirely. -To prevent their being inherited, the solution prevents the constructor +To prevent their being inherited, the implementation prevents the constructor functions from being primitive operations. However, these functions require compile-time visibility to the parent type's representation in order to construct values of the type, as this typically involves assigning values to components in the return object. The alternative approach must supply the compile-time visibility that primitive operations have. -Therefore, the specific solution is to declare constructor functions in a +Therefore, the specific implementation is to declare constructor functions in a separate package that is a *child* of the package declaring the tagged type. This takes advantage of the *hierarchical library units* capability introduced in Ada 95. @@ -331,7 +331,7 @@ Notes ----- For those interested, in this section we provide a discussion of alternatives -to the solution given, and why they are inadequate. +to the implementation presented, and why they are inadequate. Changing the behavior of an inherited operation requires an explicit conforming subprogram declaration and therefore a new subprogram body for that operation. @@ -386,7 +386,7 @@ might be called accidentally. For example: Although the overridden :ada:`Make` does not have a :ada:`Radius` parameter and could only assign some default to that component, if that default is reasonable then the overridden function could be called on purpose, i.e., not -accidentally. That's not a general solution, however. +accidentally. That's not a general approach, however. Alternatively, developers could use procedures as their constructors, with a mode-out parameter for the result. The procedure would not become implicitly @@ -437,4 +437,4 @@ But the same issues arise as with functions. Clients might accidentally call the wrong procedure, i.e., the inherited routine that doesn't have a parameter for the :ada:`Radius`. That routine would not even mention the :ada:`Radius` component, much less assign a default value, so it would have to be overridden -in order to do so. This too is not a general solution. +in order to do so. This too is not a general approach. diff --git a/content/courses/ada-idioms/chapters/controlling_obj_initialization_creation.rst b/content/courses/ada-idioms/chapters/controlling_obj_initialization_creation.rst index c39a9c7cb..5e20560d5 100644 --- a/content/courses/ada-idioms/chapters/controlling_obj_initialization_creation.rst +++ b/content/courses/ada-idioms/chapters/controlling_obj_initialization_creation.rst @@ -92,12 +92,12 @@ determined by the function, and need not start at :ada:`Positive'First`. An object cannot be used before it is declared. Since this explicit initial value is part of the declaration, the object cannot be read before it is -initialized. That fact is the key to the solutions. +initialized. That fact is the key to the implementation approaches. However, although the object declaration is guaranteed to occur, explicit initialization is optional. But unlike a procedure call, we can force the initial value to be given. There are two ways to force it, so there are two -solutions presented. +implementations presented. In addition, a specific form of explicit initialization may be required because not all forms of initialization are necessarily appropriate for a given @@ -164,20 +164,20 @@ is an example, in which a type is defined but corresponding object creation by clients is not intended. Instead, the abstraction implementation creates a single object of the type. The abstraction is a type, rather than an :ref:`ADM `, for the sake of potential -extension via inheritance. We will illustrate this design pattern and solution +extension via inheritance. We will illustrate this design pattern and implementation using a real-world hardware device. -Requiring Initialization by Clients -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Implementation(s) +----------------- There are two ways to force an explicit initial value as part of an object declaration. One is a matter of legality at compile-time so it is enforced by the compiler. The other is enforced by a run-time check. -Note that both solutions are type-specific, so when we say *objects* we mean -objects of a type that has been designed with one of these two idiom solutions. -Neither solution applies to every object of every type used in the client code. +Note that both approaches are type-specific, so when we say *objects* we mean +objects of a type that has been designed with one of these two idiom implementations. +Neither implementation applies to every object of every type used in the client code. (SPARK, a formal language based closely on Ada, statically ensures all objects are initialized before read.) @@ -198,13 +198,13 @@ creating a type that is both private and limited. Throughout this discussion we will assume that these designs are based on :ref:`Abstract Data Types `, hence we assume the use of private types. That's a general, initial design assumption but in -this case private types are required by the two idiom solutions. The types are +this case private types are required by the two idiom implementations. The types are not necessarily limited as well, but in one situation they will be limited too. -But in both solutions the primary types will be private types. +But in both implementations the primary types will be private types. -Solution 1: Compile-Time Legality ---------------------------------- +Compile-Time Legality +~~~~~~~~~~~~~~~~~~~~~ We can combine the private type and limited type building blocks with another, known as *unknown discriminants*, to force explicit object initialization by @@ -381,7 +381,7 @@ built in place instead of copied.) To recap, the primary purpose of the idiom, for a given type, is to ensure that clients initialize objects of that type as part of the object declarations. In -this first solution we meet the requirement by composing the type via building +this first implementation we meet the requirement by composing the type via building blocks that: #. require a constraint to be given when declaring any object of the type, @@ -430,10 +430,10 @@ a viable alternative, but that's also beyond the scope of this document.) Therefore, default initialization doesn't really suffice for this ADT. We need to force initialization (configuration) during object creation so that enabling -the ADT output will always be safe. This idiom solution does exactly that. +the ADT output will always be safe. This idiom implementation does exactly that. The following is a cut-down version of the package declaration using this idiom -solution, with some operations and record components elided for the sake of +implementation, with some operations and record components elided for the sake of simplicity. In the full version the unit is a generic package for the sake of not hard-coding the floating point types. We use a regular package and type :ada:`Float` here for convenience. The full version is here: @@ -573,8 +573,8 @@ parameter, the call to configure the object's state necessarily precedes any other operation (e.g., :ada:`Enable`). -Solution 2: Run-Time Checks ----------------------------------------------------------- +Run-Time Checks +~~~~~~~~~~~~~~~ Ada 2022 adds another building block, :ada:`Default_Initial_Condition` (DIC), that can be used as an alternative to the unknown discriminants used above. We @@ -668,7 +668,7 @@ all object declarations of that type that rely on default initialization. But suppose the type does not define any default initialization. We can detect these uninitialized objects at run-time if we set the DIC Boolean expression to indicate that there is no default initialization defined for this type. The -checks will then fail for those objects. That's the second solution to the +checks will then fail for those objects. That's the second implementation approach to the initialization requirement. Specifically, we can express the lack of default initialization by a DIC @@ -782,7 +782,7 @@ program a chance to execute a handler? If so, is there sufficient storage remaining to execute the exception handler's statements? In any case you can see the problem that the declaration failure semantics preclude. -Therefore, although the DIC solution is not enforced at compile-time, it is +Therefore, although the DIC approach is not enforced at compile-time, it is nevertheless sufficient to ensure no uninitialized object of the type can be used. @@ -791,11 +791,11 @@ Preventing Object Creation by Clients ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The other idiom requirement is the ability to control object creation itself. -The solution is trivially achieved using an indefinite limited private type: +The implementation is trivially achieved using an indefinite limited private type: we can prevent client object creation simply by not providing any constructor functions. Doing so removes any means for initializing objects of the type, and since the type is indefinite there is then no way for clients to declare -objects at all. The compiler again enforces this solution. +objects at all. The compiler again enforces this implementation. For a concrete example, we can apply the Singleton design pattern to represent the *time stamp counter* (:wikipedia:`TSC `) provided by @@ -804,7 +804,7 @@ clock cycle, starting from zero at power-up. We can use it to make a timestamp abstraction. As explained by :wikipedia:`Wikipedia page `, some care is required when using the register for that purpose on modern hardware, but it will suffice to -illustrate the idiom solution. Note that the Singleton pattern is itself +illustrate the idiom implementation. Note that the Singleton pattern is itself somewhat controversial in the OOP community, but that's beyond the scope of this document. @@ -825,7 +825,7 @@ times. We'll use the design approach of indefinite limited private types without any constructor functions in order to ensure clients cannot create objects of the type. The type will also be tagged for the sake of allowing type extensions. Adding the tagged characteristic doesn't change anything regarding -the idiom solution. +the idiom implementation. .. code-block:: ada @@ -1263,7 +1263,7 @@ The types above will either have a corresponding completion or a generic actual parameter to either define the discriminants or specify that there are none. As we mentioned, :ada:`Default_Initial_Condition` is new in Ada 2022. The other -solution, based on indefinite private types, is supported by Ada 2022 but also +implementation, based on indefinite private types, is supported by Ada 2022 but also by earlier versions of the language. However, if the type is also limited, Ada -2005 is the earliest version allowing that solution. Prior to that version an +2005 is the earliest version allowing that implementation. Prior to that version an object of a limited type could not be initialized in the object's declaration. diff --git a/content/courses/ada-idioms/chapters/essential_idioms_for_packages.rst b/content/courses/ada-idioms/chapters/essential_idioms_for_packages.rst index ddd6314da..e7115a452 100644 --- a/content/courses/ada-idioms/chapters/essential_idioms_for_packages.rst +++ b/content/courses/ada-idioms/chapters/essential_idioms_for_packages.rst @@ -26,8 +26,8 @@ module in relative isolation. Coupling and cohesion are interrelated: higher cohesion tends to result in less coupling. -Solution --------- +Implementation(s) +----------------- Three idioms for packages were envisioned when the language was first designed. They were introduced and described in detail in the Rationale document for the diff --git a/content/courses/ada-idioms/chapters/inheritance_idioms.rst b/content/courses/ada-idioms/chapters/inheritance_idioms.rst index c6b869aa7..b7753efef 100644 --- a/content/courses/ada-idioms/chapters/inheritance_idioms.rst +++ b/content/courses/ada-idioms/chapters/inheritance_idioms.rst @@ -90,7 +90,7 @@ types. For example, in Ada, full dynamic OOP capabilities require type declarations to be decorated with the reserved word :ada:`tagged`. However, from its earliest days, Ada has also supported a static form of inheritance, using types that are not -tagged. The solution we describe below works with both forms of inheritance. +tagged. The implementation we describe below works with both forms of inheritance. The developer also has a choice of whether the parent type and/or the child type is a private type. Using private types is the default design choice, for the @@ -178,10 +178,10 @@ with a completion in the package private part. The difference is the client visibility to the parent type. -Solution --------- +Implementation(s) +----------------- -There are two *solutions* in this entry, one for each of the two inheritance +There are two implementations presented, one for each of the two inheritance idioms under discussion. First, we will specify our building block choices, then show the two idiom expressions in separate subsections. @@ -200,16 +200,16 @@ then show the two idiom expressions in separate subsections. - We're going to declare the child type in a distinct, dedicated package, following the :ref:`ADT idiom `. This package - may or may not be a child of the parent package. This solution's + may or may not be a child of the parent package. This implementation's approach does not require a child package's special compile-time visibility, although a child package is often necessary for the sake of that visibility. - Whether the child type is visibly derived will vary with the - :ref:`inheritance idiom ` solution. + :ref:`inheritance idiom ` implementation. To avoid unnecessary code duplication, we use the same parent type, declared as a simple tagged private type, in the examples -for the two idiom solutions. The parent type +for the two idiom implementations. The parent type could itself be derived from some other tagged type, but that changes nothing conceptually significant. We declare parent type in package :ada:`P` as follows: diff --git a/content/courses/ada-idioms/chapters/interrupt_handling.rst b/content/courses/ada-idioms/chapters/interrupt_handling.rst index 3e4c6972c..7559cfac3 100644 --- a/content/courses/ada-idioms/chapters/interrupt_handling.rst +++ b/content/courses/ada-idioms/chapters/interrupt_handling.rst @@ -44,21 +44,21 @@ application code, the association of an application task to a given interrupt-driven event is convenient and common. Hence a task is often involved. How the handler procedure notifies the task -leads to a couple of different idiom solutions. In both cases notification +leads to a couple of different idiom implementations. In both cases notification amounts to releasing the previously suspended task for further execution. -In the Solution section below, we show how to express these three idioms: one +In the following section we show how to express these three idioms: one for using protected procedures alone, and two in which a protected procedure handler notifies a task. -Solution --------- +Implementation(s) +----------------- First Level Handler Alone ~~~~~~~~~~~~~~~~~~~~~~~~~ -In this solution the interrupt handler protected procedure does everything +In this approach the interrupt handler protected procedure does everything necessary and does not require a second-level handler. An interrupt handler that simply copies data from one location to another is a @@ -77,7 +77,7 @@ output is physically connected to a high-quality amplifier and speakers. No upper-level application thread requires notification of the copying: if the transfer is working the audio output occurs, otherwise it does not. -In our solution the CODEC device is *fed* from a buffer named +In our implementation the CODEC device is *fed* from a buffer named :ada:`Outgoing_PCM_Samples`. The buffer must always have new samples available when the CODEC is ready for them, because delays or breaks would introduce audible artifacts. The timing is determined by the sampling rate used by the @@ -301,8 +301,8 @@ as well as maintaining the change. Task Notification Introduction ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The first idiom solution did not require notifying a task, but these next idiom -solutions will do so. As we mentioned earlier, how the interrupt handler +The first idiom implementation did not require notifying a task, but these next idiom +implementations will do so. As we mentioned earlier, how the interrupt handler achieves this notification leads to two distinct idioms. Ultimately the difference between them is whether or not the interrupt handler must communicate with the task. In both cases the handler synchronizes with the task @@ -312,7 +312,7 @@ because of the notification required. Task Notification With Communication ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -In this solution the interrupt handler releases a task but also communicates +In this implementation the interrupt handler releases a task but also communicates with it when doing so. Therefore, a protected entry is used, and the entry parameters are the communication medium. The approach is depicted in the figure below: @@ -328,7 +328,7 @@ The dashed lines in the figure represent this data flow. By coincidence, this is the notification approach used in the idiom entry :ref:`Providing Component Access to Enclosing Record Objects `. -In that solution, client tasks call two entries to :ada:`Put` and :ada:`Get` +In that implementation, client tasks call two entries to :ada:`Put` and :ada:`Get` single characters, so the data stored in the PO consists of those characters. We did not mention it there because we were focused on that other idiom, i.e., how to give visibility within a PO/task component to an enclosing record @@ -518,7 +518,7 @@ be applied. Task Notification Without Communication ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -In this solution, the interrupt handler procedure is not required to +In this implementation, the interrupt handler procedure is not required to communicate with the task. It only needs to synchronize with it, to release it. Therefore, we can use a :ada:`Suspension_Object`: a language-defined, @@ -536,7 +536,7 @@ caller returns without suspending.) Critically, procedure returning. As a result, those are the only two routines you're likely to need, although there are others. -The interrupt handler procedure in this idiom solution simply calls +The interrupt handler procedure in this approach simply calls :ada:`Set_True` for a :ada:`Suspension_Object` (an object of that type) visible to both the handler and the task. This arrangement is illustrated by the following figure: @@ -552,13 +552,13 @@ has its ceiling priority in the :ada:`Interrupt_Priority` range, so this approach will work for interrupt handlers as well as tasks. For our example we implement a facility for sending and receiving *messages* -over a serial port, using interrupts. The design is similar to the solution we +over a serial port, using interrupts. The design is similar to the implementation we just explored, and thus to the :ref:`Providing Component Access to Enclosing Record Objects ` -idiom. In that solution, however, only single characters were sent and +idiom. In that implementation, however, only single characters were sent and received, whereas messages will consist of one or more characters. Although there are differences, we assume that you are familiar enough with that idiom's -solution that we don't need to go into all the details of the serial I/O, the +approach that we don't need to go into all the details of the serial I/O, the USART, or the interrupt handler within a PO. We'll focus instead of the differences due to this idiom. @@ -782,7 +782,7 @@ as the PO implementation of type :ada:`Suspension_Object`.) Pros ---- -In all three idioms, the solution is directly expressed, meets the +In all three idioms, the approach is directly expressed, meets the requirements, and hides the implementation details. The implementations are efficient relative to their requirements, the only reasonable metric. In particular, :ada:`Suspension_Objects` are expected to be faster than protected @@ -803,7 +803,7 @@ Relationship With Other Idioms The idiom showing how to connect a PO or task to an enclosing record object was illustrated by an interrupt handler PO, but that idiom is not necessary. -Indeed, we used a protected type directly in the last solution. +Indeed, we used a protected type directly in the last implementation. What About Priorities? diff --git a/content/courses/ada-idioms/chapters/introduction.rst b/content/courses/ada-idioms/chapters/introduction.rst index e5958899b..c636d33ce 100644 --- a/content/courses/ada-idioms/chapters/introduction.rst +++ b/content/courses/ada-idioms/chapters/introduction.rst @@ -12,7 +12,9 @@ What is an idiom? Some would say that an idiom is a workaround for an expressive deficiency in a programming language. That is not what we mean. What we have in mind are answers to the question "In this situation, -how can one best use the Ada language to express an elegant solution?". +what is the most elegant implementation approach?". Elegant software is +comprehensible, efficient, concise, reliable, and, as a result, +maintainable, so elegance is an economically and technically desirable characteristic. Design patterns [1]_ are intended to answer that question, and indeed some would equate idioms with design patterns. But what we have in mind diff --git a/content/courses/ada-idioms/chapters/programming_by_extension.rst b/content/courses/ada-idioms/chapters/programming_by_extension.rst index c7747400b..5972c4033 100644 --- a/content/courses/ada-idioms/chapters/programming_by_extension.rst +++ b/content/courses/ada-idioms/chapters/programming_by_extension.rst @@ -93,8 +93,8 @@ requirement for the :ada:`Content` type because :ada:`Values` is not a record component; anonymously-typed array objects are legal.) From the viewpoint of the language and the abstraction, the location is purely up to the developer. -Solution --------- +Implementation(s) +----------------- When you have a choice of placement, putting the state in either the package private part or the package body is reasonable, but only one of the two is diff --git a/content/courses/ada-idioms/chapters/reducing_object_code_from_generic_package_instantiations.rst b/content/courses/ada-idioms/chapters/reducing_object_code_from_generic_package_instantiations.rst index df2a70523..250a5e0ab 100644 --- a/content/courses/ada-idioms/chapters/reducing_object_code_from_generic_package_instantiations.rst +++ b/content/courses/ada-idioms/chapters/reducing_object_code_from_generic_package_instantiations.rst @@ -63,8 +63,8 @@ packages, developers should do so in a manner that minimizes the amount of object code that might result. -Solution --------- +Implementation(s) +----------------- The application source code should be written in a manner that shares the instantiations themselves, when possible, thereby reducing the number of diff --git a/content/courses/ada-idioms/chapters/type_punning.rst b/content/courses/ada-idioms/chapters/type_punning.rst index 396532ca4..fba4ca7f6 100644 --- a/content/courses/ada-idioms/chapters/type_punning.rst +++ b/content/courses/ada-idioms/chapters/type_punning.rst @@ -65,16 +65,16 @@ Unchecked conversions remain explicit, but the compiler does not limit them to the types defined as reasonable by the language. -Solution --------- +Implementation(s) +----------------- There are two common approaches for expressing type punning in Ada. We show both in the following subsections. The purpose in both approaches is to apply a different type, thereby making available a different type-specific view of the storage. -First Solution: Overlays -~~~~~~~~~~~~~~~~~~~~~~~~ +Implementation 1: Overlays +~~~~~~~~~~~~~~~~~~~~~~~~~~ The first approach applies an alternative type to an existing object by declaring another object at the same location in memory but with a different @@ -180,8 +180,8 @@ the other hand, even one Ada object with an address specified overlays that obje with the machine storage view of that address...) -Second Solution: Unchecked Conversions on Address Values -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Implementation 2: Unchecked Conversions on Address Values +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The common implementation of type punning, across multiple languages, involves converting the address of a given object into a pointer designating the