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=-0.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,7936408ed8296efa X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2001-04-18 14:00:15 PST Path: supernews.google.com!newsfeed.google.com!newsfeed.stanford.edu!canoe.uoregon.edu!logbridge.uoregon.edu!titan03.ksc.nasa.gov!niven.ksc.nasa.gov!usenet From: "Samuel T. Harris" Newsgroups: comp.lang.ada Subject: Re: User define attributes Date: Wed, 18 Apr 2001 15:50:44 -0500 Organization: Raytheon Aerospace Engineering Services Message-ID: <3ADDFE24.9B3E1038@gsde.hou.us.ray.com> References: Reply-To: samuel_t_harris@raytheon.com NNTP-Posting-Host: sstf-fw.jsc.nasa.gov Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-Mailer: Mozilla 4.7 [en] (X11; U; IRIX64 6.2 IP19) X-Accept-Language: en Xref: supernews.google.com comp.lang.ada:6987 Date: 2001-04-18T15:50:44-05:00 List-Id: Marius Amado Alves wrote: > > On Mon, 16 Apr 2001, Samuel T. Harris wrote: > > It is somewhat harder to build a generic for records > > since the "index" are the field names and the composite > > function depend upon which field is in use. But it > > can be done. > > It can? You mean without passing the names of the components explicitly, > parallelely? Please let us know how! > > I am really curious because some months ago this was briefly discussed > here on CLA and the conclusion was negative. Not even a compiler > dependent means was detected. > Lets go back to the array. It needs generic formal parameters for the width, image, and value of its index type and its component type. An instantiation provides a width, image, and value function for the composite type (i.e. the array). This is easy because an array is a homogenous collection. No matter the value of the index, the handling of components are the same. Now, compare this to records. Records are a heterogenous collection. The handling of components depends upon which component one is dealing. So, the image, value, and width functions for the components must case off of the field name and defer to the appropriate field type. This case you have to write in preparation for you instantiation. Some code examples follow ... Here is the spec for a generic which supports arrays. generic type Index_Type is (<>); type Component_Type is private; type Array_Type is array (Index_Type range <>) of Component_Type; with function Width (Item : Index_Type) return Natural is <>; with function Image (Item : Index_Type) return String is <>; with function Value (Item : String) return Index_Type is <>; with function Width (Item : Component_Type) return Natural is <>; with function Image (Item : Component_Type) return String is <>; with function Value (Item : String) return Component_Type is <>; package Array_Attribute_Functions is -- The base type of the generic index_type must have a predecessor to -- index_type'first to support returning the value of an empty image "()". function Width (Item : Array_Type) return Natural; function Image (Item : Array_Type) return String; function Value (Item : String) return Array_Type; end Array_Attribute_Functions; And here is an instantiation ... type Test_Record_Array is array (Positive range <>) of Test_Record_Type; function Width (Item : Positive) return Natural; function Image (Item : Positive) return String; function Value (Item : String) return Positive; function Width (Item : Test_Record_Type) return Natural renames Test_Record_Type_Attributes.Width; function Image (Item : Test_Record_Type) return String renames Test_Record_Type_Attributes.Image; function Value (Item : String) return Test_Record_Type renames Test_Record_Type_Attributes.Value; package Test_Record_Array_Attributes is new Array_Attribute_Functions (Index_Type => Positive, Component_Type => Test_Record_Type, Array_Type => Test_Record_Array); ... where I could have used positive'image and positive'value for the index functions, but I cannot use positive'width since it is a parameterless function. I have to define a width function which is a simple one-liner. So, for consistency I also define an image and value function. Ignore, for the moment, the fact that with width, image, and value functions for the record type have not been defined yet, that will come later. I believe the implementation of the generic body is obvious to most everyone. Image simply iterates over the index of the parameter and calls the image of the index and the image of the component, puts a "=>" finger in between, adds a separating "," after each iteration, except the last. Finally it decorates the whole thing with enclosing "()". The necessary code to satisfy the generic instantiation is trivial for arrays. Now lets look at records ... generic type Field_Type is (<>); type Record_Type is private; -- Record fields should all have default values. with function Width (Item : Field_Type) return Natural is <>; with function Image (Item : Field_Type) return String is <>; with function Value (Item : String) return Field_Type is <>; -- Width of a field of the record with default value -- must represent the largest width possible. with function Width (Field : Field_Type; Item : Record_Type) return Natural is <>; with function Image (Field : Field_Type; Item : Record_Type) return String is <>; with procedure Value (Item : String; Field : Field_Type; Into : in out Record_Type) is <>; package Record_Attribute_Functions is function Width (Item : Record_Type) return Natural; function Image (Item : Record_Type) return String; function Value (Item : String) return Record_Type; end Record_Attribute_Functions; ... which look much like the one for arrays with the following differences. 1. Instead of an index type, we have a field type. 2. Width, Image, and Value functions dealing with the component have a field_type parameter. The corresponding array function did not since the array generic know how to index the array but the record generic cannot "index" the record by field. 3. Instead of a component value function, we have a value procedure which works on the composite type. The need for a value procedure is obvious when one considers that various fields may have various types and their is no way for a single value function to support those various types. So, instead of providing a value function, the coder must prepare a value procedure which incrementally fills in a working record kept by generic body. Here is an instantiation which provided the width, image, and value function for the array generic ... type Test_Record_Type is record I, J : Largest_Integer; X, Y, Z : Largest_Float; end record; type Test_Record_Field is (I, J, X, Y, Z); function Width (Item : Test_Record_Field) return Natural; function Image (Item : Test_Record_Field) return String; function Value (Item : String) return Test_Record_Field; function Width (Field : Test_Record_Field; Item : Test_Record_Type) return Natural; function Image (Field : Test_Record_Field; Item : Test_Record_Type) return String; procedure Value (Item : String; Field : Test_Record_Field; Into : in out Test_Record_Type); package Test_Record_Type_Attributes is new Record_Attribute_Functions (Test_Record_Field, Test_Record_Type); ... The body of width, image, and value which involve components must handle the "indexing" of field names to actual record components. This is most easily done with case statements where each field alternative calls the appropriate width, image, or value function according to the field types. Each field for image and value will have its own alternative. Normally the width will also have one alternative per field. As a side note for discriminent and variant records, the discriminants should come first. The value function cannot determine the actual type of the return value until it has all discriminants. This means all discriminant need to have default values to allow record variables to polymorph. The value function simply resets the in out parameter when it know it has all the other discriminants. All three subprograms; width, image, and value; may employ sophisticated logic to handle variant records in order to avoid access invalid fields as they interate over the "index" field_type. Or they can just simply make the attempt and handle constraint_error with a very localized null exception handler. I hope that answers your questions. Since this code was written for a particular project, I am not free to release the contents. However, if there is some demand, I shall rewrite it from scratch at home and submit it to www.adapower.com. -- Samuel T. Harris, Principal Engineer Raytheon, Aerospace Engineering Services "If you can make it, We can fake it!"