There was a vote to allow dot-notation on all types recently; I dissented, and honestly would rather remove the syntax altogether, going back to Ada95-style notation.(There are several reasons for this, but that would be besides the point.) â Given the problem, itâs not exactly doable as-stated, with current Ada.
Now, I do have a proposal on abstracted types and abstracted interfaces that could help, see: this, which would allow for a definition of âpointâ on the abstract-datatype level (CS dfn. ADT) and/or on the abstract-interface level (language-construct/-usage), but this, too, doesnât address the issue now.
There are several methods you can use, though they will require some modification, simply because you are altering the design/type-definition/structure at a fundamental level; the one that will cause the least modification is the generic
-bridge:
Generic
Value : in out Point;
Package Test.Generic_Point is
X : Integer renames Value.X;
Y : Integer renames Value.Y;
-- You may have to use Import+address-overlay; this depends on visibility
-- rules for child packages; which I may be misremembering, if so then:
-- FOR OVERLAY, remove the renamings. and uncomment the following
--Private
-- Pragma Import( X );
-- Pragma Import( Y );
-- For X.Address use Value.X'Address;
-- For Y'Address use Value.Y'Address;
End Test.Generic_Point;
Once you make Point a private type, X
and Y
become invisible, which would cause compiler errors on lines like P.X := 1
â you may be tempted to fix this error, Wait!, the solution is to go to the declarative region and alter P
to something like Data_P
and add package P is new Test.Generic_Point(Data_P)
, then all your operations on P in the block become valid again.
In some cases you can use this interfacing/adaptor trick to reduce all needed modification to an added instantiation and a renames
. I use this trick âgoing the other wayâ, using the genericâs defaults, in EVILâs File and Strings to that switching between (e.g.) Character
/String
and Wide_Character
/Wide_String
is as simple as changing the instantiation of:
Package String_Package is new EVIL.Util.Strings(Character, String, ' ', others => <>);
to
Package String_Package is new EVIL.Util.Strings(Wide_Character, Wide_String, ' ', others => <>);
and letting the defaults do the rest of the work; if Iâm using EVIL.Util.Files
and supplying String_Package
to its instantiation while the appropriate Ada.[Wide_[Wide_]]Text_IO package are visible, those defaults take up the new subprograms and allow the entire subsystem to change (from String to Wide_String) based on just that alteration. (The EVIL.Utils.Files
package provides a file-type that automatically closes and has an easy/integrated stream function.)
TL;DR â When you are doing fundamental design-alterations, the code should break: to do otherwise is to invite subtle errors as the foundations mutate away from the design they were originally founded on.