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=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,e8550e5b10c2c0 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2003-02-28 12:49:38 PST Path: archiver1.google.com!news1.google.com!newsfeed.stanford.edu!news-spur1.maxwell.syr.edu!news.maxwell.syr.edu!sn-xit-03!sn-xit-01!sn-post-01!supernews.com!corp.supernews.com!not-for-mail From: "Randy Brukardt" Newsgroups: comp.lang.ada Subject: Re: Variant Record Component Date: Fri, 28 Feb 2003 14:51:43 -0600 Organization: Posted via Supernews, http://www.supernews.com Message-ID: References: <3E5D00D6.F6A20AD2@boeing.com> <3E5F8B38.EE7AE76F@boeing.com> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Newsreader: Microsoft Outlook Express 4.72.3612.1700 X-MimeOLE: Produced By Microsoft MimeOLE V4.72.3719.2500 X-Complaints-To: abuse@supernews.com Xref: archiver1.google.com comp.lang.ada:34742 Date: 2003-02-28T14:51:43-06:00 List-Id: John Harbaugh wrote in message <3E5F8B38.EE7AE76F@boeing.com>... >Here's the situation: I'm using a variant record to represent a Link 16 >(JTIDS) J7.6 message for memory-mapped I/O. So a message comes in and, >based on the message header, a particular structure is frozen. Now I >pass the message object to a decode function that is looking for >particular message fields. Well, surprise surprise, we occasionally >raise Constraint_Error because the field in question is not present. > >Several options come to mind (in order of preferance): >* Refactor the function and pass only the variant part instead of the >entire message > >* Pass the discriminant value in to the function and have the function >check it before referencing the variant part I'm confused. How can you pass the message object to a function without passing the discriminant? You can't pass part of a record in Ada, and if you're passing the whole record, you're also passing the discriminant. After all, if the generated code for the function is checking the value of the discriminant, it must be available inside the function. So, just test the discriminant inside the function. You're correct that there is no convinient syntax for doing so (which is why tagged extension records are a better choice than a variant for many uses), but certainly it can be written. If you can arrange the variants to use subtypes for their selectors, you can use memberships to make this more maintainable. This would look something like: type Code_Type is range 0 .. 100; subtype Error_Codes is Code_Type range 90..100; subtype Result_Codes is Code_Type range 1 .. 10; subtype OK_Code is Code_Type range 0 .. 0; ... type Message_Type (Code : Code_Type) is record Header : ....; case Code is when OK_Code => null; when Result_Codes => Result : Integer; when Error_Codes => Error_Message : String(1..40); ... end case; end record; function Text_Message_Decode (Message : in Message_Type) return String is begin case Message.Code is when OK_Code => return "OK"; when Error_Codes => return Message.Error_Message; when Result_Codes => return "Result=" & Integer'Image(Message.Result); ... end case; end Text_Message_Decode; By using subtypes in this way, you won't have to change any of the uses when the codes are changed (unless you add a variant). And if you add a variant, the Ada completeness checking will insure that it's added to all of the cases. Just avoid the temptation to use an others clause. We use this extensively in the intermediate code for Janus/Ada, and the checking has prevented a great many bugs. Randy.